MsCorEE

JeffGonzalez : IScalable

  • MSBuild, MbUnit 2.4 and CruiseControl.NET

    Getting all of these technologies synced up was pretty neat to see in
    action. I hadn't really done much more than a very vanilla
    installation of CruiseControl in the past. I have had a good chunk of
    time to dedicate to this project so I wanted to add some bells and
    whistles.

    At first getting MSBuild and MbUnit to place nicely was a challenge.
    For whatever reason, unless you have the MbUnit dlls in the framework
    folder and in the bin folder where your test dll is located, MSBuild
    will not execute the MbUnit task correctly.

    It feels like a hack, but I guess I can live with it. I do hope it
    gets some attention in a future release of MbUnit, but if I understand
    the problem correctly, it might have to wait for a bit.

    I ended up writing this utility MSBuild target to make sure this got
    done during a build. This target checks to see if the each of the
    MbUnit files needed to execute properly is not present in the
    Framework folder. If it isn't found (this condition is only satisfied
    on the very first run of the build), we copy the files to the
    framework folder.

    <Target Name="CopyMbUnitToFramework">
    <Copy SourceFiles="$(LibraryFolder)\$(MbUnitFrameworkDll)" DestinationFiles="$(FrameworkPath)\$(MbUnitFrameworkDll)" Condition="!exists('$(FrameworkPath)\$(MbUnitFrameworkDll)')"/>
    <Copy SourceFiles="$(LibraryFolder)\$(QuickGraphDll)" DestinationFiles="$(FrameworkPath)\$(QuickGraphDll)" Condition="!exists('$(FrameworkPath)\$(QuickGraphDll)')"/>
    <Copy SourceFiles="$(LibraryFolder)\$(QuickGraphAlgorithmDll)" DestinationFiles="$(FrameworkPath)\$(QuickGraphAlgorithmDll)" Condition="!exists('$(FrameworkPath)\$(QuickGraphAlgorithmDll)')"/>
    <Copy SourceFiles="$(LibraryFolder)\$(ReflyDll)" DestinationFiles="$(FrameworkPath)\$(ReflyDll)" Condition="!exists('$(FrameworkPath)\$(ReflyDll)')"/>
    <Copy SourceFiles="$(LibraryFolder)\$(TestFuDll)" DestinationFiles="$(FrameworkPath)\$(TestFuDll)" Condition="!exists('$(FrameworkPath)\$(TestFuDll)')"/>
    </Target>

    Once I had MsBuild and MbUnit successfully integrated, it was a simple
    matter of merging the report xml from my tests into the ccnet server
    config.


    [tags: msbuild, mbunit, cruisecontrol,continuousintegration continuous
    integration, ccnet, cruisecontrol.net]

    Read more...

  • Problems updating an svn:External in Subversion using https/ssl via CruiseControl.Net

    I have been diligently working on the build process here at work and I
    ran into an interesting problem. There is plenty of information on
    the matter on Thoughtworks website, but I wanted to post it here as a
    reference.

    The problem is an interesting one, I don't know if I can explain it
    well enough, but I will try.

    We have a couple of dependencies on third party files in our product.
    These third party files are part of our source code repository via a
    feature called Externals. I would say this is somewhat equatable to a
    symlink for Subversion. We can reference a different subversion
    repository as a directory in our repository.

    Suppose I have a repository like this:

    svnroot
    trunk
    MyCoolCode

    I put all of my local project files into the "MyCoolCode" directory.
    Let's say someone has a really cool utility library that I want to
    include in my project as well. There are several options, but
    svn:Externals allows me to check out the code from a remote repository
    down into my local files. This makes managing the consumption of an
    external project much easier.

    Back to the problem....I happen to be pulling this external codebase
    from an svn repository that is over https. So when I execute the svn
    update command from a command line for the first time, I get a warning
    or prompt stating that I need to either Reject, Accept Temporarily or
    Accept permanently the https certificate. This is all fine and dandy
    and it works when I do it manually, but my ccnet service is currently
    running under the LocalSystem account. I am just testing some things
    out with the build process in general, normally I would create a
    service account to run it under. What I ended up having to do was
    launch a cmd.exe running under the LocalSystem account and then run
    the svn update command again and permanently accept the http
    certificate.

    A bit of a beating if you ask me. The links below made it pretty easy
    to solve the issue.

    http://confluence.public.thoughtworks.org/display/CCNET/Subversion+Source+Control+Block?showComments=false
    http://confluence.public.thoughtworks.org/display/CCNET/The+Server+Service+Application
    http://blogs.msdn.com/adioltean/articles/271063.aspx

    [tags:subversion, svn, external, externals, build process, build,
    ccnet, cruisecontrol.net, http, ssl]

    Read more...

  • Anonymous methods, generics and bears...Oh my

    I stumbled across an interesting conversation on Jeff's(I am not speaking in the third person, this Jeff) blog.  Like any other time, I have plenty to say on the matter....

    Microsoft (via FxCop) suggests that you don't expose List<T> via public members.  I think the reasons I have heard mentioned in the past are around versioning your collections and the API for List<T> being too large for public APIs.

    While I don't agree with Ramon's random "suggestions" about language fluency, I do think he makes a good point about losing the flexibility of generic types by making a class directly inherit from List<T>.  With the current example (I realize this may or may not be contrived), following that route would require you to create a collection class for each class in your project. 

    I suppose you could do 1 of 2 things (if you were so inclined):

    Create a generic type that inherits from list<T>, which is pretty close to what you have.  Only a slight modification need be made:

    public class GenericList<T> : List<T>
    {
    }

    Or you could create a generic type that implements List<T> as an inner list and expose only the stuff you need from List<T>. 

    public class GenericList<T>
    {
        private List<T> _innerList;

        public MyListTwo()
        {
            _innerList = new List<T>();
        }

        public void Add(T obj)
        {
            _innerList.Add(obj);
        }

        public T Find(Predicate<T> pred)
        {
            return _innerList.Find(pred);
        }
    }
    (This one has my vote).

    Either of these would accomplish the same thing, but without the loss of flexibility.

    As for the complexity of the anonymous methods, I don't think it is bad looking at all for very simple things, most of the time you are just wanting to get an item or a series of items based on a particular property.  I do think for complex things, you should go ahead and make a method that encapsulates all of the logic for the particular predicate.

    Read more...

  • Model View Presenter Redemption

    I just wanted to clarify that I figured out my issue with the databinding.   Rookie mistake, I forgot to wrap OnItemDataBound with ItemType check.  I can't believe I missed that.  Thanks to members of the Faithful 21 (The endearing term for all of my 21 readers =P)
     

    Read more...

  • Model View Presenter Woes

    Jumping on the bandwagon for Model View Presenter.  It is something I have been intrigued with for quite awhile, but I am just getting around to implementing it.

    How come almost all of the examples for MVP are the absolute most basic thing you can think of.  Most of them seem to be edit pages also.  I get that you put properties on your View and then set those from the Presenter, but what about list pages?  Those don't seem to get enough attention.

    So I set about trying to implement a list page today and I ran into a showstopping issue.  I searched around and it seems like a lot of people have had this same issue, but I don't see it really being addressed in the way I am thinking.

    Read more...

  • ModalPopupExtender experiences

    I ran into a problem today while working with the ModalPopupExtender.  It was a self imposed problem, but it through me for a loop just the same. I made a confirmation modal window.  I have a need for a user to make a decision when they save something to the database. 

    So what I did was create a panel like this:

    <asp:Panel id="SamplePanel" CssClass="modal-popup" style='display:none;' runat='server'>
    <table>
    <tr>
    <td class="modal-content">
    <p>
    This is a message detailing a warning.
    </p>
    <p class="modal-warning">
    Do you want to proceed with this action?
    </p>
    <asp:button id="YesButton" runat="server" text="Yes" cssclass="modal-button"/>
    <asp:button id="NoButton" runat="server" text="No" cssclass="modal-button"/>
    </td>
    </tr>
    </table>
    </asp:Panel>

    This allows the user to choose yes or no, and it sets a hidden form field with this value.  I set up my ModalPopupExtender like this:

    <ajax:ModalPopupExtender 
    id="ModalPopupExtender"
    runat="server"
    dropshadow="true"
    targetcontrolid="SaveButton"
    popupcontrolid="SamplePanel"
    backgroundcssclass="modal-background"
    okcontrolid="YesButton"
    onokscript="onConfirm()"
    cancelcontrolid="NoButton"
    oncancelscript="onCancel()"/>
     
    With this I was able to popup my modal window.  I had to craft some javascript for the ok/cancel stuff still.  I did that by registering a script block from the codebehind (Thanks Shannon!).  Here it is:

    private void BuildModalScript()
    {
    StringBuilder yesScript = new StringBuilder();
    StringBuilder noScript = new StringBuilder();

    yesScript.AppendFormat("function onConfirm(){0}", Environment.NewLine);
    yesScript.Append("{").Append(Environment.NewLine);
    yesScript.AppendFormat("var hidden = $get(\"{0}\");{1}", HiddenField.ClientID, Environment.NewLine);
    yesScript.AppendFormat("hidden.value = \"true\";{0}", Environment.NewLine);
    yesScript.Append(Page.ClientScript.GetPostBackEventReference(SaveButton, String.Empty));
    yesScript.Append("}").Append(Environment.NewLine);

    noScript.AppendFormat("function onCancel(){0}", Environment.NewLine);
    noScript.Append("{").Append(Environment.NewLine);
    noScript.AppendFormat("var hidden = $get(\"{0}\");{1}", HiddenField.ClientID, Environment.NewLine);
    noScript.AppendFormat("hidden.value = \"false\";{0}", Environment.NewLine);
    noScript.Append(Page.ClientScript.GetPostBackEventReference(SaveButton, String.Empty)).Append(Environment.NewLine);
    noScript.Append("}").Append(Environment.NewLine);

    if (!Page.ClientScript.IsClientScriptBlockRegistered("onConfirm"))
    Page.ClientScript.RegisterClientScriptBlock(typeof(_Default), "onConfirm", yesScript.ToString(), true);

    if (!Page.ClientScript.IsClientScriptBlockRegistered("onCancel"))
    Page.ClientScript.RegisterClientScriptBlock(typeof(_Default), "onCancel", noScript.ToString(), true);
    }

    When I first started this little project, I was used to faking postbacks using the script like this:  __doPostBack(Control.ClientId);   Oddly that works if you set the enableeventvalidation property to true.  However, it doesn't work if your page is part of a masterpage.  The lead architect, Brian, at my new job and I were banging our heads against the wall trying to figure it out.  He knew there was something in .net that handled this but he couldn't think of the name.  I remembered seeing something like postbackreference during my travels through the documentation.  It turned out to be the correct answer.  I guess you could call it a team effort =P  It was really weird the way the problem manifested itself, because I had two different projects, it worked in one and not the other.  Once I made them exactly the same, we could see there was definitely an issue with master pages.  So chalk that one up to experience.

    In any case, I now have a nifty modal confirmation dialog.  Here is the project for vs2005 if you want to take a look.


    Read more...

  • Persistance Ignorance

    I took the plunge into Persistance Ignorance today while working on this side project that a couple of my coworkers and I have.  I have been reading about O\R Mapping, Dependency Injection, and Domain Driven Design for the past few months, but I really haven't had a chance to implement any of the ideas I have. 

    We haven't completely solved the database portion of this project yet, but I wanted to try not worrying about persistence at all.  I think you almost have to take this position if you want to concentrate on the domain.  I am also using this experience to do some TDD.  I don't quite have that down, but I am at least writing unit tests.  My goal for tonight was to rebuild my SiteMapProvider using the domain instead of Data Abstraction objects (which are very coupled to the database at this point).  I haven't quite figured out how to test ProjectSiteMapProvider class yet, so I will have to research that.

    Here is some of the code (in pseudo form for brevity) I have been playing with tonight:

    Read more...

  • Provider, Strategy, Adapter pattern discussion

    Some of my coworkers and I were having a discussion today regarding the aforementioned patterns.  First we debated the validity of the Provider pattern actually being considered a pattern, or if it was really just a renamed Strategy or Adapter pattern.

    Here is some background on the patterns for reference.  I took my definitions from DOFactory.  I use their site quite a bit when referencing patterns or when I need a refresher.

    Adapter
    Converts the interface of a class into another interface clients expect.  Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.  Forgive the Java naming conventions.  =P

    Suppose you have two separate interfaces:

    interface Iterator
    {
       HasNext()
       Next()
       Remove()
    }
    interface Enumeration
    {
       HasMoreElements()
       NextElement()
    }

    These two interfaces are pretty similar, but they have different method names and Iterator is read-write while Enumeration is read-only.   For my example, I want to adapt Enumeration to the Iterator interface.  In Java most things use the Iterator interface now, but it is possible that some legacy code might still be using the Enumeration interface.  This pattern allows us to use the Iterator interface, but provides a method to interoperate with the Enumeration interface as well.

    public class EnumerationIterator : Iterator
    {
    private Enumeration _Enumeration;
    public EnumerationIterator(Enumeration enum)
    {
       _Enumeration = enum;
    }
    public Boolean HasNext() { return enum.HasMoreElements(); }
    public Object Next() { return enum.NextElement(); }
    public void Remove() { throw new NotImplementedException(); }
    }

    Strategy
    Define a family of algorithms, encapsulate each one, and make them interchangeable.  Strategy lets the algorithm vary independently from the clients that use it.
     
    IComparable is a good example of the Strategy pattern.  IComparable defines a single member called CompareTo (Object o).  This allows different classes to define different strategies for comparison.  As long as the class implements IComparable and the CompareTo member, the implementation is up to the class itself.

    Provider
    I couldn't exactly find the definition of this pattern on DOFactory, so I looked at Rob Howard's article on MSDN.  He states, "Defined, a provider is simply a contract between an API and the Business Logic/Data Abstraction Layer. The provider is the implementation of the API separate from the API itself."

    This pattern was advocated pretty heavily by the folks at Microsoft during the .NET 2.0 framework development cycle.  The Membership API is a good example of the concrete implementation.  The Membership API contains several methods and properties like CreateUser, GetAllUsers, and ValidateUser.   By default the Membership API uses the built in providers that Microsoft developed.  They realized that Joe Developer might want to store his users in SQL Server, and Josie Developer might want to talk to Active Directory for her users.  To that end, they created the provider pattern.  I won't rehash the whole thing, but for clarification check out Rob's article.

    I think the provider pattern also happens to have a bit of Dependency Injection/Inversion of Control flavor to it.  It doesn't specifically use a container technology like Windsor or Spring.NET, but by preferring configuration over convention it allows the developer to configure their API to use a specific provider without a huge amount of coding.

    Discussion
    Our conversation today centered around whether the Provider pattern is a unique pattern or just a representation of the Strategy/Adapter patterns.  Both Strategy and Adapter seem very similar on the surface, but if you look deeper, they seem to be diametrically opposed to each other.  Implementation of the Strategy pattern seems like part of the design process, prior to coding.  You establish a need for an interchangeable algorithm and create an interface that supports it. Then you code the different implementations for each strategy.  On the other hand, the Adapter pattern seems to be sort of an afterthought. You have an established interface that maybe is used in a lot of places, but you want to adapt it to another more current interface. This is a pretty common scenario when dealing with legacy code.

    I was advocating the idea of the Provider pattern really being a Strategy.  As I mentioned earlier, the Membership API might have a different strategy for storing user data between two developers.  One developer uses SQL Server and another uses Active Directory.  My boss Shannon (sorry, no blog…yet) stated that you could argue that the Membership API was adapting each of those implementations to fit the needs of the developer.
     
    We commented that depending on your point of view the Provider pattern could fit either of those patterns, it just depends on when and where you start.

    What do you think?

    Read more...