Scott Hanselman

Twitter: The Uselessfulness of Micro-blogging

March 20, 2008 Comment on this post [13] Posted in Musings
Sponsored By

twitter20070405 I haven't used Instant Messaging for anything significant in months. Why?

Last May (!) I used the Twitter micro-blogging service and made a post every time I managed my Diabetes. It ended up being a pretty cool thing and even was on the evening News in San Francisco.

The rise of blogs brought conversations on the 'net more out in the open. Blogging enabled conversation via essay, but as blogs have matured, posts have gotten longer and longer and threads more difficult to follow. Now, most posts are jumping off points for the more interesting conversations that inevitably move to the comments.

Public debates and conversations still exist on Mailing Lists, IRC, and USENET. Private instant messaging is about connecting and conversing but is usually one to one, which certainly doesn't conserve my keystrokes. However, these conversations miss three useful things.

  • Constraints
    • Everyone uses a different mail client or USENET client and formatting and replies make things sloppy at best.
    • Some folks comment inline, other quote, still others copy-paste, all of which makes it hard to follow.
  • Permalinks
    • Yes, aggregators like Google Groups can make Permalinks (URLs) to conversations, but it's still clunky at best.
    • IRC conversations have no permalinks and virtually no searchable logs.
  • API
    • The APIs for posting and reading to and from IRC and USENET are not easy to implement (although, they are very well understood, you can't bang a client out in an hour).

Twitter offers/imposes all three. You can "tweet" a max of 140 characters. Every tweet can be linked directly to and lives forever. There's a clear API. Any one or all of these things may seem lame or a deal-breaker to you, but these very things are what makes it useful for public conversation and sharing.

Twitter as Conversation Starter

Twitter is just one of the Microblogging services out there, but it's got a nice RESTesque API that has encouraged a number of a cool Twitter Clients like Witty, Twhirl, TinyTwitter (Windows Mobile) and others, as well as a nice mobile site at http://m.twitter.com. It also supports SMS so you can send and received Twitter messages with no UI or client at all.

Twitter's API also has spawned statistics sights like Twitterholic and Tweeterboard as well as fun things like Twaiku's (Twitter Haiku's) and Twoosh, when you use exactly the maximum of 140 characters in your "Tweets."

I'm finding that I use Twitter more to chat with folks and interact with the community. There's aspects of presence, as sometimes folks will tweet "heading downtown" and I've used this to have surprise meet-ups and lunches when I just happen to cross paths with someone.

One of the misconceptions about Twitter is that I (a user) need to permissively "follow" you (another user) in order for us to talk. However, one setting change means I'll see any tweet that includes my username preceded by an @ sign. So, the way you respond in Twitter is like this: "@shanselman you rock" and I'll see it.

image

One thing to point out (warn you) about Twitter is that tweets tend to be more sarcastic, silly, non-technical, whatever than on a blog. It's important to remember that what you say on Twitter is public, indexable, and arguably permanent, which is both a good thing and a bad thing, but be aware - The Internet Remembers.

Twitter as Message Bus

There's a number of examples of Twitter being used as a message bus. For example, you can create a Twitter user as a "bot" to be used to send an receive information via an API. One such user is "commuter" that supports the http://commuterfeed.com/ website.

If I "follow" @commuter I can send traffic updates to it like this "@commuter PDX Traffic on I5" and it'll show up on the Commuter Feed.

Twitter for News

I've been getting the majority of my news lately by watching/following the major news outlets that have adopted Twitter, like NPR News, CNN and BBC Tech. Political activists like Dave Winer have been providing commentary via Twitter, and even candidates like Barack Obama have a Twitter presence. Obama has over 16,500 followers at growing on Twitter! Here's a list of the "Twitterati" from http://twitter.alltop.com/.

Twitter as Conference/Subject Tagger

If you're at a conference or in a particular special interest group, you can include a "hashtag" in your tweet like "#mix08." Many folks did this while at Mix08 in Vegas this year and via another service at Hashtags.org a feed was created that allowed not only the folks on the ground to stay in touch, but also for others not in Vegas to follow the conference.

All of these things and more have made (so far) Twitter a really fun, dynamic, and ultimately enriching part of my day.

Feel free to go sign up for Twitter yourself. I'm http://www.twitter.com/shanselman and once you've signed up you can "follow me" and I can follow you and we'll all join the conversation. I encourage you to find a Twitter Client that works for you and give it a try.

How do you find folks you know on Twitter?

You can find folks to follow by letting Twitter check your email contacts, but I have found that just by picking a few folks to follow, then watching who they talk to has been a great way to keep the signal to noise ratio high.

I don't know how long this will last, but I'm finding Twitter to be a nice, fresh way to keep up with friends and community in a 3rd place separate from USENET, Mailing Lists, IRC and IM.

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

The Weekly Source Code 20 - A Web Framework for Every Language

March 20, 2008 Comment on this post [15] Posted in Javascript | PHP | Programming | Ruby | Source Code
Sponsored By


vt102

We just keep oscillating back and forth between thin clients and chubby clients. We started with basic terminals receiving text from the server and displaying it, then added control codes and more smarts until we got into things like VT102 and beyond. We pushed all the User Interface over to the client for rendering.

Now that the Web is squarely here to stay, we've got islands of activeness in the form of browser plugins like Flash and Silverlight, some of which are cross platform and some less-so, but for now my quad-processor machine spends a lot of time either:

  • Waiting for markup to show up
  • Rendering markup

There's a thousand different ways to generate your UIs and send them down to the browser/client for rendering. Turns out there are as many ways as there are languages. If you've got a programming language, there's a web framework for it.

I don't know why this surprises me. Folks love their programming language, whatever it is, and it makes sense that the "ultimate" proof of their language's awesomeness would be the "ultimate web framework."

That said, it still seems funny to me that the greatest (er, most overtly visible) example of a language's superiority is how well it works as a Web Framework angle-bracket generator.

For example, Arc is Paul Graham's new LISP dialect that a number of people are talking about (with varying degrees of enthusiasm).  A tutorial on Arc is available here and there's an "Arc Challenge" being discussed here as folks try to this slightly more complex Hello World example:

"First generate a page with an input field and a submit button. If the user clicks on submit, he gets a second page with a link saying "click here." If he clicks on that, he gets a third page saying "you said: ..." where ... was whatever he put in the input field. This has to happen without the value being passed in the url; it should not be possible to change the behavior of the third page by editing the url in the second."

In Arc/LISP it looks like this:

  (defop said req
    (aform [w/link (pr "you said: " (arg _ "foo"))
             (pr "click here")]
      (input "foo")
      (submit)))

It's pretty terse to look at if you're used to doing things in more conventional languages. There's a lot of fun solutions like this entirely client-side one in JQuery:

$('body').append('<input id = "myInput" /><input type = "submit" />')
    .find('input[@type=submit]').click(function() {
       val = $('#myInput').val();
       $('body').html('<a href = '#'>click here</a>').find('a').click(function() {
          $('body').html('You said: ' + val);
       });
    });

Other examples include:

#!/usr/bin/env ruby
  require "ramaze"
  class MainController < Ramaze::Controller
    def index
      if f = session['foo'] then "you said #{f}"
      elsif session['foo'] = request['foo'] then A("click Here", :href => '/')
      else '<form><input name="foo" /><input type="submit"></form>'
      end
    end
  end
  Ramaze.start :port => 7001
  __END__ 

Then Rails:

def said
    if request.method == :post
      session[:said] = params[:said]
      render :action => "clickhere"
    else
      render :action => "result" if session[:said]
    end
  end

  default template said.rhtml:
  <% form_tag do %><%= text_field_tag "said", "" %><%= submit_tag %><% end %>

  clickhere.rhtml:
  <%= link_to "click here", "" %>
  
  result.rhtml:
  You said <%= session[:said] %>
| something |	
something := self request: 'Say something'.	
self inform: 'Click here'.	
self inform: something
serveAs "said" $ hasIndex $ \x -> "click me" `linksTo` (text ("You said " ++ x))
<%@ Page Language="C#" ClassName="WebApplication1._Default" %>
  <script runat="server">
    // C# and ASP.NET
    protected void SubmitButton_Click(object sender, EventArgs e)
    {
        MultiView1.ActiveViewIndex = 1;
    }
    protected void ClickHereButton_Click(object sender, EventArgs e)
    {
        SaidLabel.Text = string.Concat("You said: ", SayTextBox.Text);
        MultiView1.ActiveViewIndex = 2;
    }
  </script>

  <html>
  <head runat="server">
    <title></title>
  </head>
  <body>
    <form id="form1" runat="server">
      <asp:MultiView ID="MultiView1" runat="server" ActiveViewIndex="0">
        <asp:View runat="server">
          <asp:TextBox ID="SayTextBox" runat="server" />
          <asp:Button ID="SubmitButton" runat="server" Text="Submit" OnClick="SubmitButton_Click" />
        </asp:View>
        <asp:View runat="server">
          <asp:LinkButton ID="ClickHereButton" runat="server" Text="Click Here" OnClick="ClickHereButton_Click" />
        </asp:View>
        <asp:View runat="server">
          <asp:Label ID="SaidLabel" runat="server" />
        </asp:View>
      </asp:MultiView>
    </form>
  </body>
  </html>

Shorter but not-typical ASP.NET:

Shorter but non-idiomatic C#/ASP.NET:

    <%@ Page Language="C#" %>
    <html>
    <head>
    <title>Said</title>
    </head>
    <body>
        <form id="form" runat="server">
            <% if (!IsPostBack) { %>
                <input name="foo" />
                <input type="submit" />
            <% } else if (Request.Form["foo"] != null) {
                Session["foo"] = Request.Form["foo"]; %>
                <a href="javascript:form.submit()">click here</a>
            <% } else { %>
                you said: <%=Session["foo"]%>
            <% } %>
        </form>
     </body>
    </html>

There are so many ways to generate the same result. Big thanks to Ted Glaza for his indirect help on this post.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Getting LINQ to SQL and LINQ to Entities to use NOLOCK

March 18, 2008 Comment on this post [23] Posted in LINQ
Sponsored By

I was visiting a local company where a bunch of friends work and they asked how to get LINQ to SQL to use NOLOCK. They were explicitly asking how to get the SQL generated by LINQ to SQL to add the NOLOCK hints to the end.

However, with NOLOCK (even though "everyone" has used it at some point or another) is generally considered a last resort. Queries that use NOLOCK aren't guaranteed to return correct results or technically, return any results at all.  

SQL 2005 has snapshot-based isolation levels that prevent readers from blocking writers or writers from blocking readers without allowing dirty reads.

Now, I have said that NOLOCK has served me personally very well in the past on systems of some size, but I hear what folks who say no to NOLOCK are saying. It certainly depends on one's definition of "correct results." ;)

There's three ways to get the behavior your want. Using TransactionScope is the recommended way to affect the transaction options associated with the commands generated by either LINQ to SQL or LINQ to Entities.

LINQ to SQL also supports explicitly setting the transaction on the context, so you could get the connection from the context, open it, start a transaction, and set it on the context. This can be desirable if you think SQL 2005 is promoting transactions too often, but the preferred method is TransactionScope.

ProductsNewViewData viewData = new ProductsNewViewData();
using (var t = new TransactionScope(TransactionScopeOption.Required,
    new TransactionOptions { 
IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted
})) { viewData.Suppliers = northwind.Suppliers.ToList(); viewData.Categories = northwind.Categories.ToList(); }

Here's an example where I used it in some recent code. This TransactionScope could be hidden (layered away) in your DAL (Data Access Layer) or in your Data Context directly if you wanted it to be neater.

A second way is that you can still create and call Stored Procedures (sprocs) from LINQ to SQL and those sprocs could include NOLOCK, TransactionScope is a better choice for LINQ to SQL or LINQ to Entity generated SQL if you feel that your query doesn't need to lock down the table(s) it's reading from.

Note that you'll want to be aware of which statement in your LINQ to SQL actually starts talking to the database. You can setup a query ahead of time and it won't be executed, for example, until someone calls ToList() or the like. It's at this point you'll want to wrap it in the using(TransactionScope){}.

Another third way you could set it at a DataContext level (which, to be clear, would affect every generated LINQ to SQL query executed on that context) would be to execute the command:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

...using the connection available inside your DataContext.

Thanks to David Browne and Michael Pizzo for their help on this!

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

List of .NET Dependency Injection Containers (IOC)

March 14, 2008 Comment on this post [29] Posted in IOC | Learning .NET | Programming
Sponsored By

I'm trying to expand my mind around dependency injection in .NET (beyond the two frameworks I've personally used) and an starting to put together a list of .NET Dependency Injection Containers and IOC resources.

Here's what I've got so far. What am I missing?

What projects have I forgotten? Thanks!

Related Links

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

I'm Just a Caveman - The Hanselman Corollary to the Clarke/Wheeler Laws

March 14, 2008 Comment on this post [21] Posted in ASP.NET | ASP.NET MVC | DevCenter | Learning .NET | Programming
Sponsored By

cavemen-unfrozen-lawyer-web Any problem in computer science can be solved with one additional layer of indirection. But that usually will create another problem. - David Wheeler

Any sufficiently advanced technology is indistinguishable from magic. - Arthur C. Clarke.

These are two classic truisms. Recently while staring at some code trying to figure out what the heck was going on, I realized the obvious.

One additional layer of indirection is indistinguishable from magic. - Scott Hanselman, this morning in a rare moment of clarity while hopped up on Diet Coke.

In recent talk at Mix on ASP.NET MVC (there's video there also) I mentioned that a certain line of code was magic:

      public void Update(int id)
      {
         try
         {
            viewData.Product = db.Products.Single(p => p.ProductID == id);
            //MAGIC STARTS HERE
Binding.UpdateFrom(viewData.Product, Request.Form);
//END MAGIC db.SubmitChanges(); RedirectToAction("List"); } catch (InvalidOperationException err) { viewData.ErrorMessage = err.Message; RenderView("edit", viewData); } }

Why did it feel like magic? A few reasons.

  • It does a LOT. It takes all the values from a Form POST and lines them up with the public Properties in an object instance. This is done in the context of a Form POST to a Controller Action in ASP.NET MVC.
  • It isn't named well. Update is a verb, so that's cool, but the "From" makes me feel inverted.
  • The parameters are (possibly) in the wrong order. Given the name, I'd have expected UpdateFrom(Form, Product), but even then it doesn't feel write.

All of this adds up to an impedance mismatch, IMHO. It's too confusing and I'm just a caveman (video). As such, I declare it as black magic.

This magic was brought up to the team (I think I remember hitting someone, there may have been some swearing. ;) ) and Rob changed it in a number of good ways.

  • It's discoverable. He hung it off of the Request where you can actually stumble upon in.
  • It's named directly. Rather than the inverted UpdateFrom, it is now DeserializeTo which reads better left to right as in Request.DeserializeTo(product).
  • It's simpler. Because it's hanging off the object that was previously a parameter, it has one less parameter and again, reads nicely left to right.
//FEELS LESS MAGICAL 
Request.DeserializeTo(viewData.Product);

Jeff Moser's (see I told you I'd mention him twice) fine post talks about how cognitive "chunks" that represent solutions to problems can be more easily stored in our brains if they flow. Scott Bellware has called this concept "solubility." Code that uses frameworks with some balanced between focus on aesthetic and usability is more easily grokked.

I don't know if this is the final method, it's probably not, but I really enjoy discussions like this that aim to make things less like magic and more obvious and discoverable.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook bluesky subscribe
About   Newsletter
Hosting By
Hosted on Linux using .NET in an Azure App Service

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.