tag:blogger.com,1999:blog-70438537992478046552009-03-20T14:42:08.810-04:00amptools.netmichael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.comBlogger19125tag:blogger.com,1999:blog-7043853799247804655.post-43894408332689973212009-03-08T23:33:00.001-04:002009-03-08T23:36:13.896-04:00PDO - fetchObject<p>PDO - fetchObject or fetch(PDO::FETCH_CLASS) does not go too much into the underlying details of what it does and does not do. Fetching an object will only map fields/properties to one php Class/Type and is not smart enough to take multiple result sets and map the values to Business/Entity type of objects in PHP. </p> <p>It also will set the properties of your class before the constructor is called, which is BAD object design, so you have to be careful what you set in your constructor. </p><pre class="code php"><code>
class Person
{
public $name;
public $age;
public function __construct()
{
// overwrites the values that come for the database when
// using fetchObject with PDO
$this->name = "";
$this->age = 0;
}
}
// somewhere in your db abstraction layer tests...
$statement = $this->driver->prepare($sql);
$statement->execute($params);
$person = $statement->fetchObject("Person");
$this->expectsThat($person->name)->shouldBe("bob") // will fail: it will be ""
</code>
</pre>
<p>Because the constructor is called after the properties/fields are set, they will be overwritten by the constructor. In order to fix that you need to do something like the following.. </p><pre class="code php"><code>
class Person
{
public $name;
public $age;
public function __construct()
{
// overwrites the values that come for the database when
// using fetchObject with PDO\
if(is_null($this->name))
{
$this->name = "";
$this->age = 0;
}
}
}
// somewhere in your db abstraction layer test...
$statement = $this->driver->prepare($sql);
$statement->execute($params);
$person = $statement->fetchObject("Person");
$this->expectsThat($person->name)->shouldBe("bob") // will pass.
</code>
</pre> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-4389440833268997321?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com1tag:blogger.com,1999:blog-7043853799247804655.post-16627891628177372842009-03-08T23:06:00.001-04:002009-03-08T23:08:17.346-04:00PDO_MYSQL Troubles on Windows<p>PDO is a great idea/concept for having better abstracted layers for talking to your relational data storage. However you can't use the "newRowset" method on your PDO factory object for mysql with PHP (5.2.3 - 5.2.9) and PDO_MYSQL because it will result in this error: </p><pre class="code php"><code>SQLSTATE[HYC00]: Optional feature not implemented</code>
</pre>
<p>It's not recorded anywhere obvious, like the PDO documentation on PHP.net. In fact there isn't much to the PDO documentation on PHP.net, its seriously lacking. The error is misleading since <strong><em>its seems</em></strong> to be bubbled up from the MySql lib being used, which would be confusing to anyone reporting a bug, who might think that the PDO library itself is throwing the exception. </p>
<p>Multiple result sets should never be an optional feature and with the relationship between PHP and MySql you would think the would some collaboration with getting this issue resolved. Its been around since at least 2005. Check the <a href="http://bugs.php.net/search.php?cmd=display&search_for=nextRowset&x=0&y=0">bug list</a>. </p>
<p>One work around would be to check for windows as the OS and split the queries, which would reduce performance, but that still would not solve using stored procedures that return multiple result sets. </p>
<p>Since PHP 5.3 uses a new Mysql library MySqlND (mysql native driver), the problem is currently resolved in the beta release for windows. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-1662789162817737284?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-41583095760424742832009-01-31T06:07:00.001-05:002009-01-31T06:11:08.332-05:00VirtualBox vs Virtual PC 2007<p>With the forth coming projects at <a href="http://www.opensourceconnections.com" rel="tag">OSC</a> being heavily PHP type of projects and one never knows what kind of 3rd party applications, plugins, additional software that they may be using, its always a good idea to have a virtual workstation ready that you can copy, install, even damage without doing anything to the host operating system (aka the pc/laptop that you use for work). </p> <p>So this morning I started out creating images of windows xp and ubuntu 8.10 on virtual pc. Installing any windows product on virtual pc is pretty straight forward. Make sure that you have <a href="http://www.microsoft.com/downloads/details.aspx?familyid=28c97d22-6eb8-4a09-a7f7-f6c7a1f000b5&displaylang=en" rel="tag">Virtual PC 2007 SP1</a> installed and just install like your would on a normal pc. Getting Ubuntu to work on <a href="http://en.wikipedia.org/wiki/Microsoft_Virtual_PC" rel="tag">Virtual PC 2007</a> takes a little more work. </p> <p>You'll need to follow the instructions laid out by <a href="http://arcanecode.wordpress.com/2008/11/10/installing-ubuntu-810-under-microsoft-virtual-pc-2007/" rel="tag">arcane code instructions for install ubuntu</a> and then skip over to <a href="http://pirate-king.com/episode/3509" rel="tag">pirate-king's extra steps for installing ubuntu on Virtual PC 2007</a> which is the only way I could get it to work. Just make sure that when you restart ubuntu that you remove the attached iso or cd-rom otherwise it will boot from the cd-rom or mounted iso file. </p> <p>Then while going out to lunch with <a href="http://mindtorrent.com/blog/">Caleb</a>, recovering Microsoft Employee, he pointed out <a href="http://www.virtualbox.org/" rel="tag">VirtualBox</a>, something he is currently using, which is Sun's virtualization software (bought from innotekk). Cringing at the thought that it might be like VMware with all its annoying lil quirks and pains to the host operating system, I reluctantly installed it on windows vista 64. So far it runs great on the host operating system on top of that it has better features and higher value of reuse. </p> <p>Any image that created (at least in theory) can be used on other host operating systems OSX, unbuntu, windows, etc. So the crazy mac jobs can now run windows or unbuntu distros that also run on a windows or linux host. In a company that has various developers on various boxes, and works on cross platform projects often enough, this could help cut costs and increase productivity and start up time on a new project. </p> <p>Not only that it supports seamless windows (similar in the effect in what parallels does for the mac but works on any os), and it will also load vhd files (Virtual PC 2007 files) and the operating systems pretty much install right out of the box, no hacking around like I had to do with Virtual PC and no slugging quasi evil of VMWare. Not to mention there is an opensource version of VirtualBox as well. </p> <p>I still plan to keep using Virtual PC around, but I look forward to moving to VirtualBox, especially since they plan to support running 64bit guest systems one day. Unfortunately apple has yet to play nice and help run OSX as a guest operation system on a PC, even though there is a ton of people creating <a href="http://lifehacker.com/348653/install-os-x-on-your-hackintosh-pc-no-hacking-required">hackintoshes</a> and <a href="http://www.osx86project.org/" rel="tag">OSX86</a> versions of leopard. </p> <p>Example of seamless windows. </p> <p><object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/CSZHrjjcv6c&hl=en&fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/CSZHrjjcv6c&hl=en&fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-4158309576042474283?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-55518331272039733832009-01-29T00:59:00.001-05:002009-01-29T01:34:59.205-05:00Progress in 2009<p>I've been heads down working on various projects, so I'm using that as my current excuse/crutch for the lack of posts and not finishing up this site. I know, I know. Bad Developer BAD!!! </p> <p>I've switched this site over to server 2008 and its currently using asp.net MVC beta in conjunction with Blogger. I don't recommend that approach, but its a temp bridge till I get something working for asp.net mvc. Yes, I'm still rolling this baby out and probably will be till sometime in February. </p> <p>After my <a href="http://www.opensourceconnections.com/2009/01/08/2009-it-is-a-new-year-be-productive-but-dump-your-resolutions./">last post on the osc blog</a>, I'm going to abstain from dual posts and concentrate on this blog and hopefully get the new <a href="http://www.opensourceconnections.com/">osc website</a> up sometime this year. </p> <p> </p> <h1>Amptools.Net Themes for 2009 </h1> <ul> <li>Push for a Semantic Web - <em>(kill off IE, use of html5 today, micro-formats, what to do with HTML, etc)</em> <li>Useful Tools, Websites, "How To"s<em> - (for the parents)</em> <li>Javascript Libraries<em> - (YUI, jQuery, Prototype, etc)</em> <li>Designing a Framework - <em>(as I will be doing with amplify)</em> <li>PHP tips -<em> (even though the language sucks its not going anywhere)</em> <li>Asp.Net Mvc<em> - (leveraging rails/ruby on the .net stack)</em> <li>WPF -- Silverlight<em> - (hopefully i will get to play with edge tech this year)</em> </li></ul> <p> </p> <h1>Current OSC Projects</h1> <ul> <li><a href="http://history.state.gov/" rel="rel">history.state.gov</a> <li><a href="http://lms.acge.org/moodle/" rel="tag">Islet (Integrated System for Language Education and Training)</a></li></ul> <p>Both projects have been lots of CSS & JavaScript craziness on systems which are not kind to its designers / developers (<a href="http://exist.sourceforge.net/">eXist</a> & <a href="http://moodle.org/">moodle</a>). </p> <p><strong>eXist-db</strong> is a cool java project that is an open source xml database management system, but the java user interface for its web-dav is clunky and it makes doing any html and CSS changes time consuming.</p> <p><strong>Moodle</strong> is a <strong>c</strong>ourse <strong>m</strong>anagement <strong>s</strong>ystem written in PHP backed with various common libraries (not to be confused with CMS, content management system). It does a great deal, but it needs a complete ground up rewrite, especially to be section 508 compliant and consistent layout with consistent CSS class names, better support of html views rather than forcing you to create html via pure programming. </p> <p>So the moral to open source developers out there, be kinder to your designers and developers who are going to expand your API or theme your application, otherwise you end up increasing the barrier to entry and increasing cost to end users / end clients. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-5551833127203973383?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-10999288944075820882008-11-02T23:54:00.001-05:002008-11-03T03:02:14.267-05:00Simple Log in Amplify <p>As many people know rails has a simple logger inside the framework which really only outputs to the console. This comes in handy to see SQL output of your models, benchmarks and other cool little things inside the rails framework.  </p> <p>Of course people in the .Net realm tend to want things that scale and yet simplified for them.  So output only to the console won't fly in larger projects.  There is log4net, but you don't want to have it tightly coupled to the system, this caused an issue to one project that I worked on while still working for <a href="http://www.vivussoftware.com">Vivus Software</a> before I came <a href="http://www.opensourceconnections.com">OSC</a>. Where the framework and project both expected a certain version of Log4Net and there was no wrapper to put something else in place if need be.  </p> <span id="more-0"></span> <p>So the solution was to Build small static Log class, that takes a list of an interface ILog (different than log4net's) and then use that interface to build a wrapper around using the root Logger for log4net. This way people can still build their own loggers for amplify or build their own Appenders for Log4Net and amplify will still be able to leverage this. Of course there is also conditional symbol LOG4NET in amplify if you wish to build the amplify framework without any dependency on the log4net library.   </p> <p>To me this is more like the Console.WriteLine that is needed for a class library vs what log4net is typically used for in an application where it also spits out the type information of a class. To help with the testing using mock object is the <a href="http://code.google.com/p/moq/" rel="tag">Moq (Mock You)</a> which uses the Lambda expression and gets rid of all that crazy record/playback junk to which I loathe.  </p> <pre class="code csharp"> public void Test()
{
var id = 0;
Log.Sql("SELECT * FROM test");
Log.Debug("The id is {0} ", id);
}
[It(Order = 2), Should("have a debug method that logs debug statements")]
public void Debug()
{
var calls = new List<string>();
var log = CreateMockLog();
log.Expect(o => o.Debug(Moq.It.IsAny<string>(), null))
.Callback((string s, object[] args) => { calls.Add(s); });
calls.Count.ShouldBe(0);
// simple and easily called from anywhere... and lets you
// format messages like
// Log.Debug("item id: {0} could not be saved", id);
Log.Debug("debug", null);
calls.Count.ShouldBe(1);
calls.Contains("debug").ShouldBeTrue();
Log.IsDebug = false;
// its turned off so it won't output anything
Log.Debug("debug", null);
calls.Count.ShouldBe(1);
Log.IsDebug = true;
}
private static Mock<ILog> CreateMockLog()
{
var log = new Mock<ILog>();
Log.Loggers.Clear();
Log.Loggers.Add(log.Object);
return log;
}
</pre>
<p>Though keep in mind, one of the more trickier things to mock is the use of a method with the "params" keyword. I had to used a callback that you pass in an object array (object[] args) and I passed in null, otherwise the callback would not fire, and Lambdas don't allow the "params" keyword. Once that was figured out, I was able to use moq successfully to test the Log class successfully. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-1099928894407582088?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-34486721033228185522008-10-29T02:11:00.001-04:002008-11-03T03:02:42.100-05:00Gallio and Mb-Unit release v3.0.4<p>You can find many of the new <a href="http://blog.bits-in-motion.com/2008/10/announcing-gallio-and-mbunit-v304.html ">features over at Jeff Brown's blog</a>.  Some of the cooler features of note is the integration with the visual studio testing system, wrapping testing for exceptions into a delegate, and data store called Ambient, in which you can store state for your tests.  I've integrated this into amplify which is again, now on <a href="http://github.com/michaelherndon/amplify/tree/master">GitHub</a>. I did run into a few lil issues when setting this up though....</p> <span id="more-1"></span> <p>The biggest issue was finding out how to turn a project into a test project in order to get the visual studio integration working for Gallio. Basically you need to make modifications to the .csproj file and add an XML element of <ProjectTypeGuids> into the first <PropertyGroup> of the file.  </p> <pre class="code xml"><ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};
{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
</ProjectTypeGuids></pre>
<p>After this, I could get the Gallio tests showing up in visual studio. </p>
<p><a href="http://lh3.ggpht.com/amptools/SQf-bZnOv5I/AAAAAAAAABM/xPj4ncLlA3g/s1600-h/Gallio-Test-View%5B2%5D.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="212" alt="Gallio-Test-View" src="http://lh3.ggpht.com/amptools/SQf-b1n8cMI/AAAAAAAAABU/f0_tzJSs_Lg/Gallio-Test-View_thumb.png?imgmax=800" width="244" border="0" /></a> </p>
<p>Now this coupled with <a href="http://testdriven.net/" rel="tag">Test Driven .Net</a> really helps with the testing process especially since with certain versions of Visual Studio, Test Driven .Net will let you run visual studio's code coverage with Gallio. </p>
<p><a href="http://lh6.ggpht.com/amptools/SQf-cYepypI/AAAAAAAAABY/2DfBfKGZbZY/s1600-h/CodeCoverage%5B2%5D.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="207" alt="CodeCoverage" src="http://lh5.ggpht.com/amptools/SQf-cwXSDSI/AAAAAAAAABc/i2MQj8jhAQU/CodeCoverage_thumb.png?imgmax=800" width="244" border="0" /></a> </p>
<p>Again, one of the cooler features was the improvements to Mb-Unit's Asserts (which did change the API, but its all good, cause I wrap the Asserts that I use in BDD style mixin Methods, so I just need to change them in one place). The one really change of note would be adding Assert.Throw and Assert.Throw<T>, to which you can wrap throwing an exception into a delegate.</p>
<p><a href="http://lh6.ggpht.com/amptools/SQf-di2keqI/AAAAAAAAABg/KCLE5wy_nU4/s1600-h/WrappingExceptions%5B2%5D.png"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="178" alt="WrappingExceptions" src="http://lh3.ggpht.com/amptools/SQf-eB-bggI/AAAAAAAAABk/Tl816nR7vkw/WrappingExceptions_thumb.png?imgmax=800" width="244" border="0" /></a> </p>
<p>All in all nice improvements to both Gallio and Mb-Unit, which are now incorporated into amplify. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-3448672103322818552?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com2tag:blogger.com,1999:blog-7043853799247804655.post-76642869545874991352008-10-27T16:33:00.001-04:002008-10-27T16:33:58.990-04:00Moving Amplify To Git Hub...<p>After getting <a href="http://www.cygwin.com/" rel="tag">cygwin</a> updated, and getting much of my dev stuff on a USB drive for many good reasons and exploring using <a href="http://git.or.cz/" rel="tag">git</a> on windows.  I've decided git is stable enough to use, a good reason for me to use the command line more often and git fits more of my development needs.  </p> <p>The biggest factor is that it is its own repo on my local, so when I'm working disconnected, i can still make commits to my local drive.  The second biggest reason is the amazing merging, branching and speed at which it works.  </p> <p>Also with the code move, I'm starting over per-say, by slowly adding code only after tests are written for them, this process will put me back some, but when down, I should have a decent size test suite for amplify which is sorely needed.  </p> <p>Of course another while doing all of this I also moved a huge portion of my dev environment to my USB drive to recently having to develop on a desktop not provided for.  I was even able to get e-texteditor on a USB drive without using something like <a href="http://www.thinstall.com/">thinstall/thinapp</a>.  </p> <p>As for moving to <a href="http://github.com/">GitHub</a>, well there are not that many hosted repositories for git at this point and you really can't beat free. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-7664286954587499135?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-10450316667729072292008-08-14T14:19:00.002-04:002008-08-14T15:18:59.049-04:00Getting the |DataDirectory| folder in C sharp<p>One of the cool things about sql server express's connection strings is the ability to relatively path database files for sql express databases. Often one might see something in the connection string that looks like " AttachDbFilename=|DataDirectory|\file.mdf ". The pipes and DataDirectory is parsed to equate to a relative data directory file path that changes depending on the application type (i.e. an application deployed by click once, vs an application that is installed to a folder). </p>
<p>However sometimes you might want to know where that data directory is, like in my case, I want to take a look at a connection string and attempt to create a database based off the connection string in order to speed up development using database migrations. This could also come in handy deploying small applications. </p>
<p>So after some research via google, I found <a href="http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=702378&SiteID=1">this gem on msdn about where the DataDirectory is</a>, though not guaranteed to be accurate. It basically follows 3 simple hierarchal rules. If the AppDomain.SetData method has been used, then the directory is set there. Otherwise if the application is a click once application the data directory is set or its in the application root folder. </p> <p>So below is what the code might possibly look like in order to get the applications data directory no matter what type of application it is and it gives you ability to set the DataDirectory as well. </p> <p></p>
<pre class="code csharp">namespace Amplify
{
using System;
using System.Configuration;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Deployment;
using System.Deployment.Application;
using System.IO;
using System.Text;
using System.Reflection;
using System.Web;
public class ApplicationContext {
private static NameValueContext s_properties;
public static bool IsWebsite { get; internal set; }
static ApplicationContext()
{
IsWebsite = (System.Web.HttpContext.Current != null);
}
public static string DataDirectory
{
get
{
string dataDirectory = GetProperty("DataDirectory") as string;
if (string.IsNullOrEmpty(dataDirectory))
{
dataDirectory = AppDomain
.CurrentDomain.GetData("DataDirectory") as string;
if (dataDirectory == null)
{
if (ApplicationDeployment.IsNetworkDeployed)
dataDirectory = ApplicationDeployment
.CurrentDeployment.DataDirectory;
else
dataDirectory = Path.GetDirectoryName(
Assembly.GetExecutingAssembly()
.GetName().CodeBase);
}
dataDirectory = dataDirectory.Replace(@"file:\", "");
SetProperty("DataDirectory", dataDirectory);
}
return dataDirectory;
}
set
{
string dataDirectory = GetProperty("DataDirectory") as string;
value = value.Replace(@"file:\", value);
if (!System.IO.Directory.Exists(dataDirectory))
System.IO.Directory.CreateDirectory(dataDirectory);
SetProperty("DataDirectory", value);
AppDomain.CurrentDomain.SetData("DataDirectory", value);
}
}
public static object GetProperty(string propertyName)
{
if (IsWebsite)
return HttpContext.Current.Application[propertyName];
else
return Context[propertyName];
}
public static void SetProperty(string propertyName, object value)
{
if (IsWebsite)
HttpContext.Current.Application[propertyName] = value;
else
Context[propertyName] = value;
}
private static NameValueContext Context
{
get
{
if (s_properties == null)
s_properties = new NameValueContext();
return s_properties;
}
}
}
}</pre><div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-1045031666772907229?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-56347121962751755802008-08-06T15:35:00.001-04:002008-08-06T15:36:22.389-04:00Amplify-Fusion, JavaScript libraries compatibility layer<p>As one might start guessing, I tend to jump around languages, projects, and clients (web/windows client not people).  After writing custom code for <a href="http://www.prototypejs.org/" rel="tag">prototype</a>, <a href="http://dojotoolkit.org/" rel="tag">dojo</a>, <a href="http://developer.yahoo.com/yui/" rel="tag">yui</a>, <a href="http://jquery.com/" rel="tag">jquery</a>, <a href="http://www.asp.net/ajax/" rel="tag">atlas (microsoft ajax library)</a> , it becomes a pain to remember which library has what and to port work you've previously done into another library.  Its one thing if it porting code from one language to another, but to have port code cause of the library/framework.... its a pain that isn't needed.  </p> <p>Granted the downside of writing a compatibility layer is extra code that could be duplicated else where or writing a smaller set of routines that are less in what other full blown libraries. However most people have broadband these days and the browsers have this cool thing called caching. Not to mention YUI has a great compressor and there are ways to include multiple files on the server rather than on the browser.  </p> <p>So I've begun to embark on a long journey of making JavaScript widgets build on a compatibility layer of different libraries. The layer it self will take some time, testing, and constant refinement while trying to keep the layer small.  However I believe this is needed, esp as a consultant that works on various projects and everyone has their favorite library to use...  </p> <p>you can find the beginnings of the code at <a title="http://code.google.com/p/amplify-fusion/" href="http://code.google.com/p/amplify-fusion/">http://code.google.com/p/amplify-fusion/</a>.</p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-5634712196275175580?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-4581207136938717902008-07-28T00:33:00.001-04:002008-08-14T14:30:34.878-04:00Amplify's WCF Twitter API Client Library v0.2<p>After some playing around with WCF and Flickr, I decided to move everything internally for the twitter library to use WCF with it's <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.aspx">ServiceContract</a>.  It was more of a pain that initially thought it would be. WCF is amazingly customizable but still has a couple of downfalls thanks to REST and people not writing their API for all technologies.  </p> <p>The biggest issue is that Twitter throws an Http 403 unknown exception when you call a page and something is incorrect in the url.  Well with WCF, it throws a <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.security.messagesecurityexception.aspx">System.ServiceModel.Security.MessageSecurityException</a>, due to the url returning a status code other than 200, and it wraps the inner exceptions inside of that. </p> <p>I'm sure there is a better way to get around this, but each proxy call is now wrapped by a try/catch in the client class methods in order to check for the <a href="http://msdn.microsoft.com/en-us/library/system.servicemodel.security.messagesecurityexception.aspx">MessageSecurityException</a>, then it checks the inner exception and determines if twitter sent back a response error message. If it does the library now throws a twitter exception with error information, otherwise you would only see the WCF exception that would mask the real issue.  </p> <p>Also I renamed the "Service" classes to "Client" seeing that is the proper term for them.  The tests are now updated as well to reflect the changes.  The tests are a good way of seeing of how to use the library. Last but not least, methods now return arrays instead of lists in order to be more REST friendly. </p> <p></p> <pre class="code csharp">using Amplify.Twitter;
using System.Security;
// ... stuff
public void Test()
{
try {
string temp = "password";
Twitter.SetCredentials("Username", temp);
StatusClient client = Twitter.CreateStatusClient();
// or StatusClient client = new StatusClient("Username", temp);
Status[] tweets = service.GetUserTimeline();
} catch (TwitterException ex) {
Log.Write(ex.ToString()); // write the twitter rest error.
}
}</pre> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-458120713693871790?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com2tag:blogger.com,1999:blog-7043853799247804655.post-63910378801990049892008-07-22T08:56:00.001-04:002008-07-22T08:58:23.998-04:00Use C# to determine where and what version of java is installed<p>While writing an MsBuild Task that is calling a jar file, there was a need to find out information on the java runtime on the local machine, otherwise when I do publish the task, the developer would be required to install a specific version of java in a specific location.  That kind of thing just doesn't fly if you're writing on a 64 bit machine due to having dual "Program Files" folders, one for 64 bit programs, the other for x86.  Not only that, it really increases complexity to the end user/developer who might want to use the MsBuild Task. </p> <p>So after poking around in the registry, I found out there was information about the Java Runtime, including which version is currently the default, and where the file path is. I wrote a singleton class that looks at the registry and grabs that information.  Though usually singleton generally only checks to see if the instance is null and then instantiates it, the code below checks the registry during the "Get" method. </p> <pre class="code csharp">namespace Amplify.Tasks
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Win32;
public class JavaInfo
{
private static JavaInfo instance = null;
protected JavaInfo()
{
this.CurrentVersion = "";
this.Installed = false;
this.Path = "";
}
public string CurrentVersion { get; set; }
public bool Installed { get; set; }
public string Path { get; set; }
public static JavaInfo Get()
{
if (instance == null)
{
RegistryKey key = Registry.LocalMachine;
JavaInfo info = new JavaInfo();
string location = @"Software\JavaSoft\Java Runtime Environment";
RegistryKey environment = key.OpenSubKey(location);
if (environment != null)
{
info.Installed = true;
object value = environment.GetValue("CurrentVersion");
if (value != null)
{
info.CurrentVersion = value.ToString();
RegistryKey currentVersion = environment.OpenSubKey(info.CurrentVersion);
if (currentVersion != null)
{
value = currentVersion.GetValue("JavaHome");
if (value != null)
info.Path = value.ToString();
}
}
}
instance = info;
}
return instance;
}
}
}</pre> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-6391037880199004989?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-81647228804114584812008-07-17T06:40:00.001-04:002008-07-17T06:56:27.028-04:00Using WCF to access the Flickr JSON API<p>Even though there are quite a few opensource .Net libraries REST API out there, and a really impressive one for Flickr, they tend to never evolve or fork to use the newer framework technologies.  I think its great that they support 1.0, 2.0, and mono, but why not fork and support WCF?  I think part of the problem that .Net 3.5 use is not wide spread as it should be is not only information overload and bad naming for extension libraries, but also lack of opensource support to provide libraries and basis for current technology.  </p> <p>Flickr tends to be a little more tricky to use when calling it than some other REST APIs. WCF is a cool technology, but needs to be massaged when using it with Flickr due to a couple of gotchas and not so obvious things about WCF. In order to use Flickr, you need to register for an api_key and a shared secret code which is used to create an MD5 hash. You also need to create that MD5 each time you call a method, using the url parameters in a certain way. </p> <p>There are also a few not so obvious factors about using the JSON part of Flickr. All of the .Net libraries I've seen so far, use XML. While C# is king of parsing  XML, JSON tends to be more compact, which means less expense over the wire, though it might mean more time parsing once on the developers end point. So there are tradeoffs to using it. </p> <p>When I created the classes needed to use WCF to call Flickr, I have the actual "DataContract" object (DTO, Data Transfer Object), A Hash (Dictionary<string, object>) for adding the parameters to create the MD5 signature, A base class for creating the WCF proxy, a custom "WebContentTypeMapper", The "ServiceContract" interface, the actual "Client class", and a mixins class for creating the MD5. </p> <p>Here are some of the gotchas that I ran into while getting WCF to work with Flickr. </p> <p></p> <ol> <li>Flickr makes you create a md5 hash to send with every call for ALL parameters in alphabetical order using your "Shared Secret" Code as part of the md5.   </li> <li>Flickr's Json response "Content-Type" header is sent not as "application/json" but as "text/plain" which equates to "Raw" in WCF lingo.  </li> <li>The response object is wrapped and not obvious when it comes to json how the DataContract object should be formed.  </li> <li>Flickr will wrap the json response in a javascript function unless you pass in the parameter "nojsoncallback=1" </li> </ol> <p>To get around number one, I created an extension method that takes a Hash (Dictionary<string, object>) and adds method that converts the parameters into a MD5 string. </p> <pre class="code csharp">namespace Amplify.Linq
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
#if STANDALONE
public class Hash : Dictionary<string, object>
{
}
#endif
}
// different file
namespace Amplify.Linq
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Amplify.Linq;
public static class Mixins
{
public static string ToMD5(this Hash obj, string secret)
{
var query = from item in obj
orderby item.Key ascending
select item.Key + item.Value.ToString();
StringBuilder builder = new StringBuilder(secret, 2048);
foreach (string item in query)
builder.Append(item);
MD5CryptoServiceProvider crypto = new MD5CryptoServiceProvider();
byte[] bytes = Encoding.UTF8.GetBytes(builder.ToString());
byte[] hashedBytes = crypto.ComputeHash(bytes, 0, bytes.Length);
return BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
}
}
}</pre>
<p>Well Gotcha number two, took a bit of research to figure it out. The error I got was that it was looking for Json or XML but could not do anything with "Raw". So the solution is to create a custom binding with a custom WebContentTypeManager. </p>
<pre class="code csharp">namespace Amplify.Flickr
{
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;
using System.ServiceModel.Web;
public class JsonContentMapper : WebContentTypeMapper
{
public override WebContentFormat GetMessageFormatForContentType(string contentType)
{
return WebContentFormat.Json;
}
}
}
// different file
namespace Amplify.Flickr
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Web;
using Amplify.Linq;
public class FlickrClient<T>
{
protected string Secret { get; set; }
protected string Key { get; set; }
protected string Token { get; set; }
protected string Url { get; set; }
protected T Proxy { get; set; }
public FlickrClient(string key, string secret)
{
this.Key = key;
this.Secret = secret;
this.Url = "http://api.flickr.com/services/rest";
this.Proxy = this.InitializeProxy();
}
public FlickrClient(string key, string secret, string token)
:this(key, secret)
{
this.Token = token;
}
protected virtual T InitializeProxy()
{
// using custom wrapper
CustomBinding binding = new CustomBinding(new WebHttpBinding());
WebMessageEncodingBindingElement property = binding.Elements.Find<WebMessageEncodingBindingElement>();
property.ContentTypeMapper = new JsonContentMapper();
ChannelFactory<T> channel = new ChannelFactory<T>(
binding, this.Url);
channel.Endpoint.Behaviors.Add( new WebHttpBehavior());
return channel.CreateChannel();
}
}
}</pre>
<p>The 3rd issue, to know that all objects are wrapped in a "Response" object. To create a DataContract for the getFrob method on flickr, it took looking at the json to see what it was returning. The object below is the basic form of the Json object that is returned, it also includes the properties in case an error object is returned. </p>
<pre class="code csharp"> using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
[DataContract]
public class FrobResponse
{
[DataMember(Name = "frob")]
public JsonObject Frob { get; set; }
[DataContract(Name = "frob")]
public class JsonObject
{
[DataMember(Name = "_content")]
public string Content { get; set; }
}
[DataMember(Name = "stat")]
public string Status { get; set; }
[DataMember(Name = "code")]
public int Code { get; set; }
[DataMember(Name = "message")]
public string Message { get; set; }
}
// different file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
[ServiceContract]
public interface IAuthClient
{
[OperationContract,
WebInvoke(
UriTemplate = "/?method=flickr.auth.getFrob&format=json&nojsoncallback=1&api_key={key}&api_sig={signature}",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
FrobResponse GetFrob(string signature, string key);
[OperationContract,
WebInvoke(
UriTemplate = "/?method=flickr.auth.getToken&format=json&nojsoncallback=1&api_key={key}&frob={frob}&api_sig={signature}",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.WrappedResponse)]
Auth GetToken(string signature, string key, string frob);
}
// the actual client class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Amplify.Linq;
public class AuthClient : FlickrClient<IAuthClient>
{
public AuthClient(string key, string secret)
:base(key, secret)
{ }
public AuthClient(string key, string secret, string token)
:base(key, secret, token)
{ }
public string GetFrob()
{
string md5 = new Hash() {
{"api_key", this.Key},
{"format", "json"},
{"method", "flickr.auth.getFrob"},
{"nojsoncallback", 1}
}.ToMD5(this.Secret);
FrobResponse response = this.Proxy.GetFrob(md5, this.Key);
if (response.Code > 0)
throw new Exception(response.Message);
return response.Frob.Content;
}
}</pre> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-8164722880411458481?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-19895664017145594822008-07-16T00:40:00.001-04:002008-07-16T00:40:08.324-04:00Sample Mixins for HttpRequestBase to use with Asp.Net MVC<p>Being a semi avid user of rails for my day job, you tend to miss a couple of things that rails has that is not in Asp.Net's MVC framework. It is a great start and the control over the html (minus laziness of whoever ever developed their "Html.DropDownList" extension method, grrr INDENT YOUR NEW LINES!!), is much greater than what webforms gives you. One of the missing things that I miss is the request.xhr?, request.post?, etc methods that end to be helpful when deciding if this is an AJAX call or an actual action call to return the correct page. </p> <p>So how do you determine if the request is an ajax request or just a regular page request. What about enforcing that a page is SSL?  What about doing different things depending if the request is a GET or POST?  </p> <p>So after some googling about headers, rails, and such: here are the first go around of extension methods for HttpRequestBase that should come in handy. </p> <pre class="code csharp">public static class ControllerMixins
{
public static bool IsPost(this HttpRequestBase obj)
{
return obj.Headers["REQUEST_METHOD"].ToLower() == "post";
}
public static bool IsGet(this HttpRequestBase obj)
{
return obj.Headers["REQUEST_METHOD"].ToLower() == "get";
}
public static bool IsXhr(this HttpRequestBase obj)
{
string value = obj.Headers["HTTP_X_REQUESTED_WITH"];
return (!string.IsNullOrEmpty(value) && value.ToLower() == "xmlhttprequest");
}
public static bool IsSSL(this HttpRequestBase obj)
{
return obj.Headers["HTTPS"] == "on" ||
obj.Headers["'HTTP_X_FORWARDED_PROTO'"] == "https";
}
}</pre> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-1989566401714559482?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-39072681956227591572008-07-13T15:08:00.001-04:002008-07-13T15:27:21.947-04:00Amplify's TwitterN, Yet Another C# Twitter REST API Library<p><a href="http://code.google.com/p/twittern">http://code.google.com/p/twittern</a></p> <p>I put together a C# twitter library that uses WCF's <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx">DataContract</a> & <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx">DataMembers</a> and .Net 3.5's <a href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.json.datacontractjsonserializer.aspx">DataContractJsonSerializer</a>.  Its currently in alpha stage, as I need to finish writing the tests, documentation and make a simple WPF client for twitter.  I needed a twitter library for a personal "secret" project of mine and found that most twitter libraries do not keep up with the twitter API and break when using them. Plus they tend to go to great lengths when parsing the xml.  Unfortunately I do not know if this will work on mono yet. It seems that they have "<a href="http://www.mono-project.com/WCF">Olive</a>", which is mono's version of WCF and I've seen where they have a path for the "DataContractJsonSerializer".  If there are any one familiar enough with mono, please by all means use the code, join the project.  </p> <p>One design decision that I made was to use Json rather than xml as its more compact and less data to transfer.  I used WCF because with DataContract & DataMembers you can parse Json and you can name your properties the property way with Pascal Case properties and then tell wcf what attributes of json they represent. This way you don't have properties that look like ruby like "screen_name" or  "profile_sidebar_border_color" in your <a href="http://martinfowler.com/eaaCatalog/dataTransferObject.html">Data Transfer Object</a> in order to deserialize the Json response from twitter. </p> <p> </p> <p>A basic sample of how to use the library is below. </p> <pre class="code csharp">
using Amplify.Twitter;
using System.Security;
// ... stuff
public void Test()
{
SecureString password = new SecureString();
string temp = "password";
for (var i = 0; i < temp.Length; i++)
password.AppendChar(temp[i]);
password.MakeReadOnly();
Twitter.SetCredentials("Username", password);
StatusService service = Twitter.CreateStatusService();
// or StatusService service = new StatusService("Username", password);
List<Status> tweets = service.GetUserTimeline("MichaelHerndon");
}
</pre> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-3907268195622759157?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com3tag:blogger.com,1999:blog-7043853799247804655.post-2111218432183871802008-07-10T09:45:00.001-04:002008-07-10T09:48:29.548-04:00Determining Development/Testing Mode in .Net<p>One of the things I'm trying to do with amplify is attempt to force as little configuration upon the developer as possible. However one does need to know what time of environment the code is currently executing in order to do specific things, like using different databases for testing, development, and production. One of the problems to solve with this is having amplify compiled in a non-debug mode and still determine if the developer is in a "development" mode or even "test" mode. Testing is generally going to have its own testing project, so this can be manually set in something like an "AssemblyFixture". testing. </p> <p>That being said, when a developer is debugging, it should be in 'development' mode since you need that extra debug information as well an application is usually debugged when being developed. The 'test' mode should be when a developer is running automated unit tests that should go hand in hand with some kind of data fixtures being loaded for those tests. An example of what I'm currently doing in the "Amplify.ApplicationContext" class is currently below. </p> <pre class="code csharp"> static Constructor
{
IsWebsite = (System.Web.HttpContext.Current != null);
System.Web.Configuration.CompilationSection section
= (System.Web.Configuration.CompilationSection)
ConfigurationManager.GetSection("system.web/compilation");
IsDevelopment = (section != null && section.Debug);
if(!IsDevelopment)
IsDevelopment = System.Diagnostics.Debugger.IsAttached;
}
public static bool IsWebsite { get; internal set; }
public static bool IsDevelopment { get; set; }
public static bool IsTesting { get; set; }</pre>
<pre class="code csharp"> [FixtureSetUp]
public void InvokeOnStartUp()
{
try
{
ApplicationContext.IsTesting = true;
}
catch (Exception ex)
{
Console.WriteLine(ex);
Assert.Fail(ex.ToString() + "\n stack trace: " + ex.StackTrace);
}
}</pre>
<p>Of course there might be a better solution as always, but for now this will do and I'm definitely open to suggestions. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-211121843218387180?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-74864195276594606382008-06-12T17:25:00.001-04:002008-06-12T17:25:50.641-04:00Pursuit of Rails like Active Record for C#<p>After trying <a href="http://msdn.microsoft.com/en-us/library/bb425822.aspx" rel="tag">linq to sql</a>, <a href="http://msdn.microsoft.com/en-us/library/aa697427(VS.80).aspx" rel="tag">the ado.net entity framework</a>, php's <a href="http://codeigniter.com/">code igniter</a> framework, php's <a href="http://www.cakephp.org/" rel="rel">cake framework</a>; I'm realizing how much of rails really depends on the inner workings of ruby itself to do what it is able to do.  I've looked and poked around <a href="http://www.cakephp.org/" rel="rel">Castle's Active Record</a> and it does some heavy lifting, but it still seems to deviate too much from rails's version of active record.  One of the key things of porting a concept, is to keep it as close as possible so that developers can rely more on the same convention without having to relearn the concept in a different domain specific language.  Plus, I cringe a little when it leans too much on using <a href="http://www.hibernate.org/343.html" rel="tag">NHibernate</a>. </p> <p>It goes back to the whole "Don't make me think principle", that developers often to have to keep in mind when developing for an end user.  At first, I was thinking about creating a port would be simpler using linq with either "linq to sql" or the currently released "ado.net entity framework". After investigating, it would take a ton of invested time to either write a code generator for visual studio that would changed the way the pocos (plain old c# objects) are generated in order in corporate the changes. Also not to mention that these frameworks heavily rely on a repository pattern, that would probably cause too much pain to change for just one developer.  </p> <p>Square one?  Well close enough. C# and ruby have different strengths and weaknesses. However with enough thought and using C#3.0, I think its completely possible to get something that closely resembles rails enough to give anyone who has worked with rails, something that would be familiar if they needed to work on a project in .Net.  </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-7486419527659460638?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-14427530089582145202008-04-09T16:46:00.001-04:002008-04-09T16:46:34.070-04:00Thoughts on Developing a Linq To SQL Layer<p>Amplify is going to have a Data Namespace that will serve as a basis for dealing with data including, validation, database migrations & fixtures similar to rails and even give some basic patterns to use.  One of these patterns will be an Active Record pattern and another will be a Repository pattern, since the repository tends to favor <a href="http://msdn2.microsoft.com/en-us/library/bb425822.aspx">Linq to Sql.</a> </p> <p>One of the biggest debates on <a href="http://msdn2.microsoft.com/en-us/library/bb425822.aspx" rel="tag">Linq to Sql</a> is whether or not it supports the <a href="http://www.lhotka.net/weblog/ShouldAllAppsBeNtier.aspx" rel="tag">NTier</a> scenario. Of course many people are still confusing the difference between physical Tiers and virtual layers in code (DAL is a data access layer, not a tier). Linq to Sql can support layers out of the box, depending on how the developer uses the generated objects.   Linq to Sql does not support WCF out of the box and you pretty much have to really massage Linq to Sql in order work disconnected, even within a Web Environment the default tight <a href="http://www.west-wind.com/weblog/posts/162336.aspx">relationship between an object and the DataContext</a> can be a bit of a pain. Linq to Sql does follow Domain Driven Design heavily. </p> <p>With <a href="http://www.asp.net/mvc/">Asp.Net Mvc</a> on the horizon, I think it would be proper for a Linq to Sql to have some form of an <a href="http://martinfowler.com/eaaCatalog/activeRecord.html" rel="tag">Active Record</a> harness that provides much of the same functionality as possible as the <a title="tag" href="http://wiki.rubyonrails.org/rails/pages/ActiveRecord">Rail's Active Record</a> does. Obviously c# is not ruby and a developer can not do everything the same way in c# that you can in ruby.  A good reason to get as close as possible to rails api for active record is to simply help developers who know specific concept like rails active record to hit the ground running with Amplify.  </p> <p>The reason I see for doing creating an Active Record for Linq to SQL is so that you can wrap validation, business/domain logic and encapsulate it into one object, versus having to know where the separate rules are kept for data, which can create a simpler api for the developer and clue a person to in to what the domain entity is capable of and should be able to do.  This would hopefully shield the developer from being tempted to do the following with Linq to Sql, which could lead to invalid data or even worse.  </p> <pre class="code csharp"> private void Bind() { // bad practice
using(DataContext db = CreateContext()) {
this.datagrid.DataSource = (from o in db.Clients select o);
this.datagrid.DataBind();
}
}</pre>
<p>Which is a good reason for Amplify to help provide some basic interfaces and even base classes / wrappers for Linq. Now the question is, what do you support? Do support the linq objects that sqlmetal generates, provide your own CodeGen tool for Visual Studio?  Since <a href="http://msdn2.microsoft.com/en-us/library/bb386987.aspx" rel="tag">SqlMetal</a> generates the partial on<strong><em>PropertyName</em></strong>Change methods which are crude and does not help to reduce code or really support code reuse. If you support classes that SqlMetal generates, you need to use some form of Reflection or a Linq Expression to do any kind of business rules evaluation of the incoming values.  Do you create your own kind of UnitOfWork pattern and force Linq To Sql to work disconnected and keep track of your own changes, if not what is the best way of keeping track of the DataContext that your object is now tied to?  </p>
<p>And if you do your own UnitOfWork pattern, you have to either add a binary timestamp or int version to the table or you have to keep the intial values of the object stashed or you have to fetch the current object in the database in order to use DataContext.GetTable<T>().Attach(entity, oldEntity); Not exactly what I would call very performant (yes I know, its not in the dictionary, but I like the word performant). </p>
<p>If you have any comments, suggestions, questions, feel free to drop me a line. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-1442753008958214520?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-86876981534899581822008-04-05T20:49:00.001-04:002008-04-05T20:56:20.987-04:00Gallio & Mb-Unit 3 With BDD style tests, I mean specs<p><a href="http://www.amptools.net/content/users/michaelherndon/images/GallioMbUnit3withBDDstyletestsImeanspecs_11EDC/behaviordrivendevelopmentex.jpg"><img style="margin: 0px 0px 10px 25px" height="148" alt="Only sky is the limit" src="http://www.amptools.net/content/users/michaelherndon/images/GallioMbUnit3withBDDstyletestsImeanspecs_11EDC/behaviordrivendevelopmentex_thumb.jpg" width="240" align="right" /></a><a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">BDD</a>, Behavior Driven Development, is basically a fusion of <a href="ttp://en.wikipedia.org/wiki/Domain_driven_design">Domain Driven Design</a> and <a href="http://www.amptools.net/content/users/michaelherndon/images/GallioMbUnit3withBDDstyletestsImeanspecs_11EDC/behaviordrivendevelopmentex.jpg">Test Driven Development</a> (what is with you developers and your love for acronyms, I'll never know, maybe it comes from developing software in the government sector?). The basic premise has to do with business value of handing over code that is maintainable and readable specific to their domain, versus an over all process/methodology change like going from <a href="http://en.wikipedia.org/wiki/Agile_software_development">Agile</a> to <a href="http://en.wikipedia.org/wiki/Waterfall_model">Waterfall.</a> Granted projects like <a href="http://rspec.info/">Rspec</a> have added much to the overall terminology that <a href="http://dannorth.net/introducing-bdd">Dan North first came up with (Given, When, and Then).</a> BDD is an attempt at having a Domain Specific Language for code and having a mechanism that supplies the company, business, client, or whoever that must maintain that application, with what the application "should" do given in a certain context, i.e. specifications written in code. </p> <p>Following to what I previously posted on the <a href="http://www.opensourceconnections.com/blog/">OSC blog</a>...with <a href="http://www.opensourceconnections.com/2008/03/19/catching-up-net-for-bdd-and-unit-testing-with-gallio-nbehave-and-moq/">ramping up .net for BDD</a>, and spending time working with <a href="http://www.gallio.org/" rel="tag">Gallio</a> and MB-Unit 3.0, and time in thought about BDD in general and how it relates to .Net, I've come to some conclusions as I want to set the standard for writing tests/specifications for both <a title="tag" href="http://code.google.com/p/amptools">Amptools</a> and <a href="http://code.google.com/p/amplify-net" rel="tag">Amplify</a>.</p> <p>The obvious one is, <strong>c# is not ruby</strong>. <a href="http://rspec.info/" rel="tag">Rspec</a> can add keywords to ruby since ruby is a dynamic language and you can pre parse a file that is code, then execute it. C# is heavily tied to the default IDE Visual Studio for most developers and it would be a pain to create your own keywords, but at the same time, typing long sentences and having underscores in your method names that should be Pascal cased according to <a href="http://blogs.msdn.com/brada/articles/361363.aspx">MS standards</a> is just ugly.</p> <p>Gallio makes good use of meta Attribute tags such as Mb-Unit's AuthorAttribute, CategoryAttribute, and TestsOnAttribute. Gallio's GUI client, Icarus, lets you sort by these attributes for running tests. The DescriptionAttribute however is only visible when running the reports, though it would be nice if it were readable/visible in the GUI as well. </p> <p>Rspec has a "Describe" keyword that basically encapsulates description for a spec, which is often related to a class somewhere else. You can rename the TestsOnAttribute to become "Describe" and now you can categorize all your specs/tests that tests on a certain class. You can also Describe something in different contexts, to which the DescriptionAttribute can help you describe in what context you are using writing this specification for, which would <a href="http://rspec.info/examples.html">replace the nested "describe" keywords in rspec</a>. </p> <p>Obvious Replacements would be renaming FixtureSetupAttribute to "BeforeAll" for Rspecs "before(:all)", FixtureTearDownAttribute to "AfterAll", SetupAttribute to "BeforeEach", and TearDownAttribute to "AfterEach". Rename the TestAttribute to "It", DescriptionAttribute to "Should", AuthorAttribute to "By", and CategoryAttribute to "Tag" (since we're in that web 2.0 tag everything phase. </p> <p>What you might end up with is something below, which is a code specification for a "ValidatePresence" class which comes from a localized prototyping version of Amplify that I have on my local drive.</p> <pre class="code csharp">namespace Amplify.Data.Validation
{
#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MbUnit.Framework;
using Describe = MbUnit.Framework.TestsOnAttribute;
using InContext = MbUnit.Framework.DescriptionAttribute;
using It = MbUnit.Framework.TestAttribute;
using Should = MbUnit.Framework.DescriptionAttribute;
using By = MbUnit.Framework.AuthorAttribute;
using Tag = MbUnit.Framework.CategoryAttribute;
#endregion
[
Describe(typeof(ValidatePresence)),
InContext("should validate the presence of a value."),
Tag("Functional"),
By("Michael Herndon", "mherndon@amptools.com", "www.amptools.net")
]
public class ValidatePresenceObject : Spec
{
[It, Should(" have a public default constructor. ")]
public void InvokeConstructor()
{
ValidatePresence obj = new ValidatePresence();
obj.ShouldNotBeNull();
obj.RuleName.ShouldBe("ValidatePresence");
}
[It, Should(" validate the value passed to the object. ")]
public void ValidateValue()
{
ValidatePresence obj = new ValidatePresence();
obj.DefaultValue = "";
obj.Validate("").ShouldBeFalse();
obj.Validate("Has Value").ShouldBeTrue();
obj.If = (value) => !string.IsNullOrEmpty((value as string));
obj.Validate("").ShouldBeTrue();
}
}
}</pre>
<p>In case you are wondering where all the ".Should" methods are coming from, they are c# extension methods that I've created that are stemmed from Assert methods found in the typical testing library such NUnit or Mb-Unit. I was using <a href="http://nbehave.org/">NBehave</a> for the extension methods, but I didn't care for the tight coupling with Rhino Mocks, especially when I'm going to be using <a href="http://code.google.com/p/moq">Moq</a> as the Mock Object Library. </p>
<p>Now in Icarus, I can sort by TestsOn, Category and Namespace, and in the Reports generated by Gallio, I get all the above, plus the Description. Sooner or later, it would be wise to add a plugin to Gallio to generate a specification type of report, that would generate specifications for anyone would wanted to use Amplify or Amptools. </p>
<p class="blog-music">currently listenting to.. <a class="artist" href="http://www.last.fm/music/D12/">D12</a> on <a class="album" href="http://www.last.fm/music/D12/Devil's+Night/">Devil's Night</a> performing <a class="track" href="http://www.last.fm/music/D12/_/Purple+Pills/">Purple Pills</a></p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-8687698153489958182?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/17310931859288502137noreply@blogger.com0tag:blogger.com,1999:blog-7043853799247804655.post-8996589338813456852008-04-04T05:50:00.000-04:002008-04-05T15:00:52.993-04:00Simplicity<blockquote> <span class="quote">Working on the complexity that is always indirectly implied by simplicity.</span> </blockquote> <p>Simplicity. <em>"Simplicity is the property, condition, or quality of being simple or un-combined. It often denotes beauty, purity or clarity."</em> <a href="http://www.en.wikipedia.org/wiki/Simplicity">en.wikipedia.org/wiki/Simplicity</a>. It is very rare in today's world for anything to really be simple from the inside out. Often, when someone states a simple "truth", we automatically understand the statement without really tracing back how much we had to learn and gain in order to obtain the complex knowledge to understand something that sounds simple when communicated out loud. </p> <p>You probably have an idea of where I am going with this. Very few things are as simple as they seem or should be. Anyone who has worked in the software industry or any other major industry for any length of time knows how it always sounds simple when someone utters it, but that is rarely the case, because of all the implied complexity and all the details that are often not apparent in that statement.</p> <p>I'm currently employed with <a href="http://www.opensourceconnections.com/">Opensource Connections</a>, to which one of their strongest core components is developing thought leadership. From that, stems the B.H.A.G (big, hairy, audacious goals), a project or multiple projects that develop thought leadership. Now before anyone jumps to conclusions that this site or the opensource projects that I've been working on, is just to fulfill some quota, it's not. On I've been wanting to write a .Net framework and tools that applies patterns and practices that allows  underrated within the .Net community. Or the framework could be sufficient in itself. But the biggest part of this that I want to accomplish is bringing Simplicity to everything the framework touches on.</p> <p>I'm calling the framework "Amplify" and the tools ... wait for it..... .....drum roll..... "Amptools" (ugggh naming conventions, but it beats Microsoft naming conventions). The idea in mind is that the framework and tools should amplify your project and its output. Probably the biggest way of keeping simplicity is "<em>convention over configuration"</em>, but that is not always plausible, so convention should offer a way to be changed to fit the developers environment. </p> <p>Now, semi off-topic, one of the simplest ways to encourage use of other source libraries in .Net is unit testing code. However, since the concept of <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">BDD</a> is fairly new, but seems worth exploring, I have decided to take this approach, while leveraging <a href="http://www.gallio.org/">Gallio</a>, the neutral testing platform, in its current alpha state, along with Mb-Unit 3.0. More on this in the next post. </p> <div class="blogger-post-footer"><img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7043853799247804655-899658933881345685?l=amptools.net.web7.reliabledomainspace.com%2Fpublic%2FIndex.aspx'/></div>michael herndonhttp://www.blogger.com/profile/18050530794057789472noreply@blogger.com0