Useful to have a anon method?


I'm writing some code to get a snippet of text back from a passed in string.  I initially came up with:

        protected string Snippet(string text, int length)
        {
            text = StripBbCode(StripHTML(text));
            int spaceIndex = length;

            if(text.Length > length)
            {
                spaceIndex = text.IndexOf(' ', length);

                bool spaceExists = spaceIndex != -1;
                if(!spaceExists)
                {
                    spaceIndex = text.Substring(0, length).LastIndexOf(' ');
                }
                spaceExists = spaceIndex != -1;
                if(!spaceExists)
                {
                    spaceIndex = length;
                }
            }
            return text.Substring(0, spaceIndex);
        }

Then I got to thinking, would this be a good place to plop in an anonymous method?

        private delegate bool SpaceExists(int spaceIndex);

        protected string Snippet(string text, int length)
        {
            text = StripBbCode(StripHTML(text));
            int spaceIndex = length;

            SpaceExists spaceExists = index => index != -1;

            if(text.Length > length)
            {
                spaceIndex = text.IndexOf(' ', length);

                if(!spaceExists(spaceIndex))
                {
                    spaceIndex = text.Substring(0, length).LastIndexOf(' ');
                }
                if(!spaceExists(spaceIndex))
                {
                    spaceIndex = length;
                }
            }
            return text.Substring(0, spaceIndex);
        }

Which is better?  While the anon method is cooler, I think the prior is more readable.  I just wonder if there are other benefits.  Or is there a better way to do this?  Neither feels very good because I'm duplicating the same is = to -1 twice.

 

Update:  All tests passing and what I ended up with:

    [TestFixture]
    public class For_Snippet : BaseViewModel
    {
        [Test]
        public void When_Length_Less_Than_Space()
        {
            const string text = "[b]1<b>2</b>34[/b] 6789";

            string expected = "1234";
            string actual = Snippet(text, 4);

            Assert.That(actual, Is.EqualTo(expected));
        }

        [Test]
        public void When_Length_Equal_To_Space()
        {
            const string text = "[b]1<b>2</b>34[/b] 6789";

            string expected = "1234";
            string actual = Snippet(text, 5);

            Assert.That(actual, Is.EqualTo(expected));
        }

        [Test]
        public void When_Length_More_Than_Space()
        {
            const string text = "[b]1<b>2</b>34[/b] 6789";

            string expected = "1234";
            string actual = Snippet(text, 6);

            Assert.That(actual, Is.EqualTo(expected));
        }

        [Test]
        public void When_No_Space()
        {
            const string text = "[b]1<b>2</b>34[/b]";

            string expected = "1234";
            string actual = Snippet(text, 4);

            Assert.That(actual, Is.EqualTo(expected));
        }

        [Test]
        public void When_Long_With_No_Space()
        {
            const string text = "[b]1<b>2</b>34[/b]56789";

            string expected = "1234";
            string actual = Snippet(text, 4);

            Assert.That(actual, Is.EqualTo(expected));
        }

        [Test]
        public void When_Length_Out_Of_Bounds()
        {
            const string text = "[b]1<b>2</b>34[/b]";

            string expected = "1234";
            string actual = Snippet(text, 24);

            Assert.That(actual, Is.EqualTo(expected));
        }
    }

 

On:

        private delegate bool SpaceExists(int spaceIndex);
        protected string Snippet(string text, int length)
        {
            text = StripBbCode(StripHTML(text));

            SpaceExists spaceExists = index => index != -1;

            if(text.Length <= length)
            {
                return text;
            }
            int spaceIndex = text.IndexOf(' ', length);

            if(!spaceExists(spaceIndex))
            {
                spaceIndex = text.Substring(0, length).LastIndexOf(' ');
            }
            if(!spaceExists(spaceIndex))
            {
                spaceIndex = length;
            }
            return text.Substring(0, spaceIndex);
        }

author: WTF | posted @ Thursday, March 12, 2009 6:44 PM | Feedback (0)

jQuery: Is a checkbox checked?


A few different ways, but the one that I find the most readable is:

$('#checkbox-id').is(':checked');

author: WTF | posted @ Wednesday, March 04, 2009 9:52 PM | Feedback (0)

Having your computer wake you up


I've often thought that instead of the alarm clock, it would be nice to have my computer wake up for me in the morning and then wake me up by playing some of my favorite tunes.  What a headache it would be to program though, and who's got the time.  Seems Dennis Babkin did with WakeupOnStandBy.  The utility essentially wakes your computer at the specified time, and then does whatever command you want it to do.  To become an alarm clock you simply specify a playlist that you'd like to play upon wake up time.  Bam, alarm clock.  And shoot, that took 5 minutes.

image

author: WTF | posted @ Monday, February 09, 2009 6:43 PM | Feedback (0)

Code Quality, not a matter of if, but when


I just read an article by Uncle Bob.  The blog post essentially states a direct counter to the Stack Overflow #38 podcast from Joel and Jeff plopped out.  Uncle Bob obviously knows a ton more about software than I do and with my coder hat on I totally agree with him. 

Wierdly enough, I don't think Joel and Jeff are wrong either though.  I think in today's day an age if you are putting a new product out there quality of the code doesn't matter <b>until</b> you actually have an audience using your code.  Once you have that, then I think it's the refactor time to go back in make sure your code coverage is high and the app is solid.

Until then what's the point?  Think about it, if you have a truly awesome product, the code smells great, 95% coverage everything's great on that end, but no one uses it.  Did you suceed? 

We're talking about 2 guys that coded something up in a matter of weeks, sure the code my stink a bit, but is there site stackoverflow.com successful?  Seems to be so far.  At this time I would think that they would now have a person implementing features, while 2 or so other people started refactoring and writing the tests to back the software up.

Why test until you need to?

Now...if they were developing the product for someone else, then it's a different matter.  In this case you have a super small team, with a tightly focused project, small code base, I just don't see the problem of not having 90% coverage.

author: WTF | posted @ Monday, February 02, 2009 9:06 AM | Feedback (0)

Getting back a strong type from app settings


What do you think of this?

 

protected TYPE GetApplicationSettings<TYPE>(string key) where TYPE : IConvertible

{

   string keyValue = System.Configuration.ConfigurationManager.AppSettings.Get(key);

   return (TYPE)Convert.ChangeType(keyValue, typeof(TYPE));

}

author: WTF | posted @ Friday, January 30, 2009 3:00 PM | Feedback (0)

Lego Mindstorms Competition


What a good time.  After attending a few sessions at the last So Cal Code Camp, the last session, a Lego Mindstorms Competition was up to bat.  Thomas, our presenter had 4 little square robots that 4 groups were going to try to use to push each other out of a circular ring.  There were a bunch of different sensors that we could use, 30 minutes, and the brain power of the group.  My son also was able to come in to "play with Lego's" and the wife and daughter joined in a little later. 

Take note that only one person in the entire classroom of people had ever touched a Lego Mindstorm kit, and they had only done one program.  The rest of us were pretty clueless and 30 minutes didn't seem like much time.  Strangely enough my group only had me and another dude, the other teams were comprised of 5-6 people, but that was pretty cool as there was less discussion about the approach we were going to take.  Surprisingly in the first few minutes we were able to get our robot moving and rotating.  I was "driving" by inserting commands as fast as possible into the machine, compiling, uploading it onto the robot, and then seeing what it'd do.  It was a ton of fun.

Getting to the competition with only seconds to spare as I inserted one last angled turn to try and bisect the largest portion of the circle had us pretty pumped.  With the code camp raffle underway we decided to do that and I missed the first round.  We won anyway, not sure what happened.  The next round was pretty interesting.  Our robot hit the front corner of the other robot's head and both robots went into a spin of death.  Our robot kept inching the other out of the circle, but it was taking awhile.  Thomas almost called the match a draw but we said, "Just a few more rotations" as we analyzed the competitors algorithm and noticed that the back sensor was about to hit the line and was going to go the other direction.  Sure enough on the next revolution it tagged it, backed right into our sweet spot and our robot shoved the sucker right out of the ring, and then actually reversed after it was finished to "find" more adversaries.  How freaking cool it was to have everyone yelling and having a good time (yes as my wife noted, we are nerds).  With that win we were in the finals.

I can almost say it was like having your mind on the mat for you actually fighting the other mind in a physical space.  You could totally tell as the competitor complained that "that's not my algorithm!" as we tried a test run before the final bout.  You see, the other team in the finals had the dude that had experience programming the robots.  I looked over at his program and it was pretty complex.  There was a lot of logic.  I thought we were screwed.  Weirdly enough though, on our first try after all the kinks were worked out and they were satisfied, their robot simply left the circle!  Win!

That was chalked up to a fluke though (I think it had to do with the logic loop latency screwed with their program) so we had another go.  Our robot again found it right away and bashed it out of the ring.  My son looked at me and was like "We won Dadda!"   High fives for the team!  The nerd ego was flowing though so the other team conceded just like a nerd would, "It was a hardware problem" and let it go.  We then were presented with our Lego #1 and that was it.

After the event I came away with a few revelations:

1) We had a non-programmer on our team, my wife.  She pointed out that "Well if you hit the robot, you want to keep pushing not back out".  Duh!  We had it just going to the line and then backing away.  She didn't know the first thing about actually programming the device, but her "business analyst" sense was right on the money.

2) After seeing a question on da stack I can safely say that my kids will be ready to program when they want to, if ever.  Me taking my son to the event wasn't to have him learn about programming, it was to hang out with Dad and play with some Lego's.  For some reason I really like to insert him into mature situations and see what he does.  He's a very good 5 year old, and I'll never forget his face after we pushed the final robot out of the ring.  If he picks up on programming, that's cool, but so are a lot of other things in life.

3) The smaller group (only 5 people - 2 kids, 1 wife and 1 programmer) really allowed us to keep a good focus on the task at hand.  We threw some ideas out there, saw what stuck and then kept refactoring till we had something solid.  Our design was simple in principle, so I was able to adjust at the very last minute to great affect.  Everyone on the team had bought into our ideas, and we were able to act on them quickly and precisely.  I'm not sure if on a larger team any of my own ideas would have been heard let alone the discussion of "why" to get 4 other people's buy ins to do it.

author: WTF | posted @ Monday, January 26, 2009 9:52 PM | Feedback (1)

SoCal Code Camp this weekend


Hit it up if you can.  I went to the last one and it was pretty fun.  Of course I was all by myself so it felt like the first day of school or something.  They did have a geek dinner last night but it was about an hour away from me so was a no go.  One day I will go to those.  One area I saw that was missing was ASP.NET MVC in general.  Maybe I should have tried to give a talk.  Man would that be a change from my usual shy self, but would be a fun experience.  Probably next time.  The one that has me the most interested, funny enough is the Lego Mindstorms competition.  Always interested in combining real world objects with code.  Would be a gentle entry I'm sure.

author: WTF | posted @ Saturday, January 24, 2009 8:32 AM | Feedback (0)

Using JQuery with ASP.NET MVC to post data


I've seen some examples of how to do this, but they are older than the beta release and none seems to handle the entire process of posting to the server, and then displaying a result from that data on the screen using JQuery.  JQuery makes this process really simple (is anything really hard with JQuery?) but it took a bit of figuring so I thought I'd share.  All of the methods were also different so I have my own take.  Just remember that there are lots of ways to do things with JQuery, so modify to your needs.  For my example I am again using Spark, as I think it kicks serious butt.

What I have is essentially a thread or discussion listing.  It looks like:

<table cellpadding="7" border="1" width="100%">
  <thead>
    <tr>
      <td colspan="2">    
        <h1>${thread.Topic}</h1>
        Replies: ${thread.NumberOfPosts - 1} |  Views: ${thread.Views} | Score: ${thread.Score}
      </td>
      <td align="right">Email me when this is replied to</td>
    </tr>
  </thead>
  <tbody id="posts">
  <for each="var message in messages">
    <tr>
      <td>${message.PostedBy.NickName}</td>
      <td>Posted: ${message.Posted}</td>
      <td align="right">Quote Message</td>
    </tr>
    <tr>
      <td valign="top" nowrap="nowrap">
        Joined: ${message.PostedBy.Joined.ToShortDateString()}<br />
        Standing: ${message.PostedBy.Standing}<br />
        Location: ${message.PostedBy.Location}
      </td>
      <td colspan="2">
        ${message.Comment}
      </td>
    </tr>
    <tr>
      <td><a href="javascript:scroll(0,0)">Back to top</a></td>
      <td>PM | Email</td>
      <td align="right"></td>
    </tr>
  </for>
  </tbody>...

I would like to allow the user to add another message to this thread.  So I give them something like:

<form action="~/Message/New" method="post" id="newMessage">
<input type="hidden" id="threadId" name="threadId" value="${thread.Id}" />
Post Comment<br />
<textarea id="comment" name="comment" style="width:100%;" rows="4"></textarea>
<input type="button" value="Post Message" id="postMessage" />

And over in my MessageController I'd have something like:


    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult New(FormCollection form)
    {
      Message message = new Message();
      message.Thread = _repository.Get<Thread>(int.Parse(form.Get("threadId")));
      message.Posted = DateTime.Now;
      message.PostedBy = _userService.FindUserBy(User.Identity.Name);
      message.Comment = form.Get("comment");
      message.Score = 0;
      _repository.Save(message);
      ViewData["Message"] = message;
      return View("New");
    }

Here, I tried to use the TryUpdateModel but the threadId wasn't playing nice with Message's Thread property.  Instead I had to load it up.  If you know a work around I'd love to know about it.  Now, if you don't need anything back, replace ActionResult with void and don't return anything. In my case though I want to show the posted message on the page, so I shove the message into my ViewData and render the New.spark view.  That looks like a slice of the above thread html.  In fact I copy and pasted it like this:

<viewdata message="Message" />
<content name="page">
<tr>
  <td>${message.PostedBy.NickName}</td>
  <td>Posted: ${message.Posted}</td>
  <td align="right">Quote Message</td>
</tr>
<tr>
  <td valign="top" nowrap="nowrap">
    Joined: ${message.PostedBy.Joined.ToShortDateString()}<br />
    Standing: ${message.PostedBy.Standing}<br />
    Location: ${message.PostedBy.Location}
  </td>
  <td colspan="2">
    ${message.Comment}
  </td>
</tr>
<tr>
  <td><a href="javascript:scroll(0,0)">Back to top</a></td>
  <td>PM | Email</td>
  <td align="right"></td>
</tr>
</content>

This brings me to a hiccup that I encountered.  You might need to modify your master page (Application.spark).  A "use" tag around the entire master page will allow you to only output what we need, and not the entire page.  Normally we'd want to insert content within the master page, but for this we just want a snippet of html.  To further illustrate what I'm talking about, here's a sample from Application.spark:

 

<use content="page">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

...

</html>
</use>

 

This makes sure that I only output the tr snippet from above.  There might be a different work around for this, and again I'm all ears, but for now this worked great.  Now that we have all of that in place it's time for us to bring it home with some JQuery script.

<script language="javascript">
  $(document).ready(function() {
    $("#postMessage").click(function() {
      $("#newMessage").fadeOut("slow");
      var form = $("#newMessage");
      var action = form.attr("action");
      var serializedForm = form.serialize();
      $.post(action, serializedForm, postAdded, "html");
      return false;
    });

    function postAdded(html) {
      $('#posts').append(html);
      $("#newMessage").fadeIn("fast");
    }
  });
</script>

 

I'm using the click event, but I believe you could also turn it into a submit button and handle a onsubmit event.  This might work better for browsers with javascript not enabled, but I'll have to investigate that further.  Once it's clicked I hide the postMessage box, grab the form, get it's action attribute, serialize the data from the form, and then use the .post to post to my controller in an ajax fashion.  Within the post you can see that my callback method is postAdded, this will fire when my New controller is finished with the snippet on my view.  I've specified "html", but it seems that this is not needed.  I kept it to remind myself that there are other data types that can be returned like "json", in case I decide to construct the html within the postAdded method instead or something.

Now that the html snippet is returned and passed into the postAdded method, I simply grab my post's tbody tag , #posts and then appending the snippet.  Then I make the comment box reappear.  Nifty!

author: Willie | posted @ Friday, January 09, 2009 10:39 AM | Feedback (2)

Control Adapters are like weak Kool Aid


After analysing, changing, and implementing a control adapter for the menu control I don't see the point.  I started off with the CSSFriendly adapters which were great and all, but then noticed that a CSS only solution wouldn't work for me.  I then started to tinker, and at the end, I'm thinking a custom control would have done the same thing but had more with less code.

I would say that if you have a ton of existing controls or existing controls that inherit parent .net controls then use the adapters as it's literally no work involved to get a better CSS format out of the controls.  However if you need to customize a specific control's output and you don't have it up on the page yet, use a custom control.  I'm already planning on ripping the code out of the adapter to place it into it's own control.

author: Willie | posted @ Wednesday, January 07, 2009 2:35 PM | Feedback (0)

OpenId's Attribute Exchange is the Problem not DotNetOpenId


As I suspected, DotNetOpenId is doing it's job fine, it's the Attribute Exchange that's the problem, or more specifically that none of the providers can pick a schema to use.  See this informative overflow q&a.  Looks like if you are going this route, use Simple Registration.  Now where's an example of that using DotNetOpenId?

author: Willie | posted @ Tuesday, January 06, 2009 9:06 AM | Feedback (2)