Darrell Hawley: Home Page

Thursday, September 10, 2009

Does IronPython need LINQ?

Before I get started, I think I need to clear up some misconceptions that the Python community might have about LINQ. From the posts I’ve read, Python developers have dismissed LINQ as only a series of language enhancements that allow for SQL-like querying of lists. Though it is true that both C# and VB.NET have made changes to their respective languages for working with lists, you can still use LINQ without the aforementioned language enhancements. Python developers would be better served to think of LINQ as wrappers around the map, filter and reduce functions. In fact, LINQ is not much different than the “recipes” found in the official itertools documentation.

So the question still stands: does IronPython need LINQ? In my last post, I described how to use LINQ from an IronPython application and implied that I didn’t think it was the best idea. Don’t get me wrong, I really enjoy writing LINQ statements, I just don’t think LINQ fits well with IronPython. Why not? The first problem I have with the IronPython/LINQ combination is put on prominent display in this code sample.

print Enumerable.Average[object](
    list, Func[object, int](lambda x:x))

If you are a static language aficionado, you probably are wondering what the problem is. If you’re a Python developer, however, the fact that I’m explicitly naming the “object” and “int” types is sending up giant, red flags. Python folks don’t really care what type of object it is they’re using, they only want to know what the object can do and what it contains (i.e., duck-typing). It’s much easier – and more readable - to simply write a completely Python version of the Average function. Consider the following chunk of LINQ code from C#:

List<string> values = new List<string>("the quick brown fox jumped over the lazy dogs".Split());

double avgLengthOfLongWords = values
                .Select(x => x.Length)
                .Where(x => x > 3)
                .Average();

Console.WriteLine(avgLengthOfLongWords)

To convert that to IronPython, we’d be forced to write something like the following:

import clr
clr.AddReferenceToFileAndPath("c:\users\darrell\desktop\System.Core.dll")

import System.Linq
from System import Func
from System.Linq import Enumerable

stuff = "the quick brown fox jumped over the lazy dogs".split()

def Select(col, func):
    return Enumerable.Select[object, object](col, Func[object, object](func))
def Where(col, func):
    return Enumerable.Where[object](col, Func[object, bool](func))
def Average(col):
    return Enumerable.Average[object](
    col, Func[object, float](lambda x:x))

avgLengthOfLongWords = Average(Where(Select(stuff, lambda x:len(x)), lambda x:x > 3))
print avgLengthOfLongWords

Before I’m even able to write useable code, I need to add a reference to a dll, import a namespace and a couple of classes and then write some helper functions; all so that I can write LINQ statements without the benefits of chaining. That’s right – I have to nest my LINQ statements. No chaining. That’s because when we use IronPython, the Select and Where don’t return an IEnumerable or an IQueryable. Instead they returna WhereSelectEnumerableIterator.

But do you know what really rankles me about using LINQ in IronPython? It contributes absolutely nothing to the Python community. The only way you can use LINQ is if you are using IronPython, not CPython, not Jython. I want to engage the entire Python community, not just my corner of the world. If ever there was a case where implementing the principle trumps migrating the implementation, this is it.

Enter the itertools module. Itertools is a Python standard library module containing tools for working with iterators. It also will serve as the cornerstone for my implementation of LINQ. When you visit the official itertools documentation at python.org, you’re even presented with code “recipes” that could be described as LINQ-ish. The only problem is that the recipes only accomodate nesting of statements. Why is this a problem? Consider the differences in readability between nested and chained in the following example:

stuff = "the quick brown fox jumped over the lazy dogs".split()

getLength = lambda x:len(x)
isNotTooLong = lambda x:x<6
isNotTooShort = lambda x:x>3

nested = ifilter(isNotTooShort, ifilter(isNotTooLong, imap(getLength, stuff)))

chained = IterHelper(stuff).select(getLength).where(isNotTooLong).where(isNotTooShort)

As always is the case with nesting methods, you have to read the statement populating nested backwards. That is, the outermost function call is the last to be run and you work your way inwards from there to find the origin. This is not a big deal to most of us since this is something we had to get used to very early in our careers. But when you compare that to the statement populating chained, I know I can read it from left to right. My eyes aren’t jumping back and forth to understand what is happening in what should be a relatively simple statement.

So what does IterHelper look like?

class IterHelper(object):
    def __init__(self, someIterable):
        self.someIterable = someIterable
    def __iter__(self):
        return self.someIterable
    def next(self):
        return self.someIterable.next()
    def select(self, func):
        return IterHelper(itertools.imap(func, self.someIterable))
    def where(self, predicate):
        return IterHelper(itertools.ifilter(predicate, self.someIterable))

This extremely simplistic version of IterHelper is really only a wrapper around functions found in the itertools module. This is great news since any application written using Python 2.3 or later can make use of this pattern with little effort. There’s no special libraries AND everyone is invited regardless of your flavor of Python.

My plan is to release IterHelper as an open source project by sometime by mid-October. I have a well-tested, basic implementation now, but I still have questions regarding licensing, hosting and deployment. I will be doing a bit of research on these topics and be posting what I’ve learned in my Notes to Self series.

Labels: , ,

Saturday, August 15, 2009

IronPython and LINQ: A Devlink Correction

During my “Anatomy of an IronPython Application” presentation at Devlink, I mistakenly said that LINQ can be consumed from IronPython easily. I said this because I was thinking that IronPython 2.6 was built using .NET 3.5 when in fact it’s built with .NET 2.0. Fortunately, if you want to use LINQ, you still can because .NET 3.5 is really .NET 2.0 plus extensions; you just have a bit of extra work to do. First on the todo list is to copy the System.Core.dll for 3.5 to some other location (I was able to get to it from it’s home in the c:\windows\assembly directory) and then use the “clr.AddReferenceToFileAndPath” in your IP code to gain access. Then, with a simple import of the Enumerable or Queryable type, you magically have access to LINQ.

Still, the story doesn’t end there. You have to remember that IronPython does NOT support extension methods and since LINQ is pretty much a collection of extensions methods, there’s a problem. Why this design decision? Because in order to support extension methods, the IronPython team would have had to make changes to the core language which would have, of course, been rather un-Pythonic. This means that the code for consuming LINQ is going to be somewhat messy. The following snippet gives an example of consuming the Average function of the Enumerable object.

clr.AddReferenceToFileAndPath(r"C:\folder\System.Core.dll")
from System.Linq import Enumerable
from System import Func

list = [1,2,3,4,5]

print Enumerable.Average[object](
    list, Func[object, int](lambda x:x))

I have a lot of concerns as soon as I see “object” and “int” in brackets. At this point I’m going to hold save those concerns until my next post. Instead I’m going to leave this as an example of consuming LINQ from IronPython.

I should point out that Harry Pierson’s post on IronPython and Linq-to-XML really got me started on this topic. I also have to give a shout-out to Chris Smith who was kind enough to help me out and relay a couple of CodeMash stories at the same time.

Labels: , ,

Tuesday, July 14, 2009

Book Review: IronPython in Action

IronPython in Action (IPIA) gets the distinction of being the first book published on IronPython. As the first book, it has the responsibility of giving developers their first impression of IronPython. IPIA does exactly that by taking numerous shallow dives into various technologies and techniques. To be clear, this book is aimed at professional developers preferably with either .NET or Python experience. Pythonistas will find the book offers quick introductions to a number of Microsoft technologies such as Windows Forms, WPF and ASP.NET. .NET developers will get the chance to see technologies they’re already familiar with expressed in a completely new fashion.

IPIA avoids the trap of simply being a brochure of Microsoft technologies using “IronPython” in place of “C#” and “VB.NET”. Instead, the authors mix in chapters on development techniques ranging from the familiar - such as unit testing and mocking – to the more exotic such as metaprogramming. As .NET developers wind their way through the book, they’ll begin to appreciate the differences between the static and dynamic worlds – a crucial step toward wide ranging acceptance.

If you’re curious about what IronPython can do for you, IronPython in Action is well worth your time.

Labels: , ,

Friday, May 29, 2009

Note to Self 9 – Exploring SharpDevelop and Going off Topic

It’s been too long since I last blogged which typically means I have too many competing ideas to settle on just one. So welcome to Note to Self 9!

  • SharpDevelop is an open source IDE for the .NET platform. Is it new? Hardly. Based on the history of news releases from their website, It’s been around since December of 2000. Considering that the .NET platform was publicly announced only 6 months earlier, SharpDevelop seems only that much more mature.
  • If you’re comfortable with the basics of Visual Studio, SharpDevelop should feel like home to you. In fact, the best way to describe SharpDevelop is “Visual Studio without a lot of stuff I don’t want and a few thid-party items I do”.
  • SharpDevelop uses NUnit instead of MSTest. That’s right. No third party plugins to make your IDE work with NUnit. It simply works.
  • It’s time for me to confess. It’s all about IronPython. The reason I started investigating SharpDevelop is because of my frustration with Visual Studio’s lack of support for the language. Specifically, I want Intellisense when I write IronPython. To be sure, you only get Intellisense for “non-DLR code”, but surprisingly that doesn’t seem to be as much of a handicap as you might think.
  • Speaking of first class citizens, SharpDevelop comes stock with C#, Visual Basic, Boo (I can hear Jay Wren cheering now), IronPython and F# (now a number of SRT folks are cheering).
  • If you’re frightened of the consequences that may come from changing your development environment, don’t be. You can open one of your existing Visual Studio solutions with SharpDevelop and start coding. Switching back is as simple as opening up your now modified project/solution in Visual Studio.
  • For clarity, SharpDevelop is new to me. I haven’t used SharpDevelop for any projects yet so I can’t tell you about any of its nuances. I plan on putting it to the test, however, over the next several weeks. I’ll be posting about my experiences.
  • Now for the off-topic part. I’ve been listening to The History of Rome, a FANTASTIC podcast series on, well, the history of Rome. Mike Duncan, creator and narrator, is not only an engaging story teller, but also has the technical savvy to put together a professional podcast. Though it’s not the sort of podcast typically on a geek’s menu, I think there are enough parallels to some of the challenges we are facing in the software industry to make it worthwhile.

Labels: , , ,

Sunday, March 15, 2009

Writing an IronPython WCF Host

This is a simple WCF host written in IronPython that consumes a library I wrote in C#.

import clr
clr.AddReferenceByPartialName("System.ServiceModel")
clr.AddReferenceByPartialName("CSharpClass")

from System.ServiceModel import ServiceHost, BasicHttpBinding
from System.ServiceModel.Description import ServiceMetadataBehavior
from CSharpClass import PersonService, IPersonService
from System import Array, Uri

uri = Uri("http://localhost:1234/people")
uriArray = Array[Uri]([uri]) # creates a generic array of type Uri
serviceHost = ServiceHost(PersonService, uriArray)

binding = BasicHttpBinding()

serviceHost.AddServiceEndpoint(IPersonService, binding, "http://localhost:1234/people")

behavior = ServiceMetadataBehavior()
behavior.HttpGetEnabled = True
serviceHost.Description.Behaviors.Add(behavior)

serviceHost.Open()

raw_input("Service has been started. Press Enter to exit...")

Labels: , ,

Friday, March 06, 2009

Running nose with IronPython

I just spent the past week at the 2009 Microsoft MVP Summit where I got a chance to talk to the some of the crew behind the dynamic languages at Microsoft. When I mentioned that I had gotten nose, a Python unit testing framework, working with IronPython, I was strongly encouraged to blog about it. Without further adieu, here's my code.

import sys
sys.path.append(r"C:\Python25\Lib\site-packages\nose-0.10.4-py2.5.egg")
sys.path.append(r"C:\python25\lib")
sys.path.append(r"C:\Python25\Lib\email")
sys.path.append(r"C:\Python25\Scripts")
import nose
nose.main()

I dropped this script into a directory with a couple of bogus unit tests and ran it with Python 2.5.4. Results were consistent with my expectations - successful tests passed and failing tests threw exceptions. When I ran the same suite against IronPython 2.0.0, I still received the correct results but the script took 1 minute and 20 seconds to complete. Compare that to less than a second (estimated) for CPython. For the sake of completeness, I ran the same test with IronPython 2.0.1 and received the same result.

The root of the problem appears to be the large number of GeneratorExitExceptions being thrown. I'm not sure why they're being thrown, but I'll continue to investigate and report my findings. If you're interested in the gory details, here's the stack trace of the first exception:

at IronPython.Runtime.PythonGenerator.ThrowThrowable()
at IronPython.Runtime.PythonGenerator.CheckThrowable()
at IronPython.Runtime.PythonGenerator.
CheckThrowableAndReturnSendValue()
at IronPython.Runtime.Operations.PythonOps.
GeneratorCheckThrowableAndReturnSendValue(Object self)
at S$11.lambda_method$312(Closure , Int32& state, Object& current) in C:\python25\lib\types.py:line 52
at Microsoft.Scripting.Runtime.GeneratorEnumerator`1.
System.Collections.IEnumerator.MoveNext()
at IronPython.Runtime.PythonGenerator.MoveNextWorker()
at IronPython.Runtime.PythonGenerator.System.
Collections.IEnumerator.MoveNext()
at IronPython.Runtime.PythonGenerator.throw(Object type, Object value, Object traceback)
at IronPython.Runtime.PythonGenerator.throw(Object type)
at IronPython.Runtime.PythonGenerator.close()

Labels: , , ,

Friday, February 20, 2009

IronPython Exception: [A]Person cannot be cast to [B]Person

Had an interesting problem while using the Hosting API the other day. Here's the exception message.

[A]CSharpClass.Person cannot be cast to [B]CSharpClass.Person. Type A originates from 'CSharpClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadNeither' at location '[project directory]\bin\Debug\CSharpClass.dll'. Type B originates from 'CSharpClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location '[temp directory]\CSharpClass.DLL'.

I was struggling with this for a while until I found this link. In order to get my IronPython scripts to communicate with my CLR-based code, I was using the clr module's AddReference methods. These methods require you to point at the appropriate copy of the library you want to consume. I do stress "copy". Let's say you point your IronPython script at the bin\debug folder of a C# library project you're consuming in a console application. When you run the application, you'll get the exception message above. To make this example work, you'd have to point your IronPython script at the bin\Debug folder of your console application instead. Clearly, this is a maintenance nightmare. Instead, insert the following chunk of code into your hosting application (in the example described above, your console application) to avoid the problem all together.

Assembly assembly = typeof (CSharpClass.Person).Assembly;
runtime.LoadAssembly(assembly);

Labels: , ,

Wednesday, February 04, 2009

Note to Self 8 - IronPython2, Hosting, DLR

  • The latest DLR code and documentation can be found at www.codeplex.com/dlr
  • For the examples below, here is the Python script I'm using
  • class Person(object):
        def __init__(self, name, phone):
            self.name = name
            self.phone = phone
        def TalkToCSharp(self):
            val = {"name":self.name, "phone":self.phone}
            return val

     

    def GetPerson():
        person = Person("darrell", "555-4321")
        return person.TalkToCSharp()

    def GetPersonWithParams(name, phone):
        person = Person(name, phone)
        return person.TalkToCSharp()

    theNumberFive = 5
    myPerson = GetPerson()

  • Simplest thing you can do is execute a Python script.

  • static void ExecutePythonScript(string path)
    {
        ScriptRuntime runtime = Python.CreateRuntime();
        runtime.ExecuteFile(path);
    }

  • Sometimes you need to get a variable after a script has run.
  • static void GetDoubleVariable(string path)
    {
        ScriptRuntime runtime = Python.CreateRuntime();
        ScriptScope scope = runtime.ExecuteFile(path);
        object x = scope.GetVariable("theNumberFive");
        Console.WriteLine(x);
    }

  • What happens if you're trying to return a custom class defined in the script? The easiest - and IMHO the best - way to go about this is to convert the object to a dictionary before passing it to your C# code.
  • static void GetInstanceCustomClass(string path)
    {
        ScriptRuntime runtime = Python.CreateRuntime();
        ScriptScope scope = runtime.ExecuteFile(path);
        PythonDictionary dictionary =
            scope.GetVariable("myPerson")
            as PythonDictionary;
        foreach (var property in dictionary)
            Console.WriteLine(property.Key +
                " == " + property.Value);
    }

  • Getting properties is definitely useful, but you'll probably want to call a function.
  • static void CallingAFunction(string path)
    {
        ScriptRuntime runtime = Python.CreateRuntime();
        ScriptScope scope = runtime.ExecuteFile(path);
        ObjectOperations op =
            scope.Engine.CreateOperations();
        ObjectHandle handle =
            scope.GetVariableHandle("GetPerson");
        var x = op.Call(handle, new object[0]);
        PythonDictionary dictionary =
            x.Unwrap() as PythonDictionary;
        foreach (var property in dictionary)
            Console.WriteLine(property.Key +
                " == " + property.Value);
    }

  • Here's an example of passing parameters to a Python function.
  • static void CallingAFunctionWithParameters(string path)
    {
        ScriptRuntime runtime = Python.CreateRuntime();
        ScriptScope scope = runtime.ExecuteFile(path);
        ObjectOperations op =
            scope.Engine.CreateOperations();
        ObjectHandle handle =
            scope.GetVariableHandle("GetPersonWithParams");
        var x = op.Call(handle, "Larry", "555-1234");
        PythonDictionary dictionary =
            x.Unwrap() as PythonDictionary;
        foreach (var property in dictionary)
            Console.WriteLine(property.Key +
                " == " + property.Value);
    }

Labels: , , , ,

Thursday, January 29, 2009

Note to Self 7 - Naming Python Modules, SciTE, IronPython and __name__

  • Be careful naming your Python modules. If you name a Python file the same as an existing file in your Python install directory, you may get the following exception message: "'module' object has no attribute '[some-attribute-name]'".
  • I'm really loving SciTE. It's a dead simple code editor that offers syntax highlighting for an impressive number of languages and displays the results of the run in it's own output window.
  • More SciTE: If you decide to use SciTE, you'll probably want to customize how it works. Here's a nice quick reference to supplement the SciTE documentation to help guide you through the config files.
  • If you want to use SciTE as your IronPython editor, you'll need to modify the existing python.properties file. Select "Open python.properties" from the "Options" menu. Search for "command.go" and modify the value so that it points at your IronPython directory.
  • All Python modules have a special variable called "__name__". When the code in your module is executed with CPython, __name__ is set to the file name of your module minus the "py" extension ("mymodule" if the file name of your module is "mymodule.py", for example), except when the module is executed directly. If that's the case, __name__ is equal to "__main__". Unfortunately, this is not the case if you execute it with IronPython. The special variable __name__ will always be based on the file name. UPDATE: The above is true only when you compile your IronPython code. If you launch a *.py file with ipy.exe, the __name__ variable will be "__main__".

Labels: , , ,

Monday, January 19, 2009

Note to Self 6 - IronPython, pyc.py and SciTE

  • The pyc.py file can compile you IronPython code into .NET executables.
  • The pyc.py file is part of the sample code released with IronPython. It can be found here. Look for the "IronPython-2.0-Samples.zip" link.
  • Typing out "[IP directory]\ipy [code directory]pyc.py" explicitly everytime you want to use the tool is somewhat annoying. Consider creating a script to do this for you. Here's a simple batch file.

    cd C:\data\FeClass
    c:\fepython\ipy.exe pyc.py class.py /main:main.py

    Note that you'll have to copy the pyc.py file to the same directory as your code for this to work.
  • IronPython Studio just isn't up to snuff. You're better off to use a text editor and a build script
  • I like SciTE as my IronPython editor even more so than Notepad++. I really like that I can run my Python or IronPython script from SciTE and the output the normally would be displayed in the command window is captured in SciTE.

Labels: , ,

Sunday, February 18, 2007

Another AADND Success

We had another great night at AADND! On Wednesday night, Jennifer Marsman kicked off our meeting by introducing us to some of the basics of 3D graphics in Windows Presentation Foundation (WPF). She introduced us to XAML - the markup lanuague behind WPF - and introduced us to some of the considerations we are need to be aware of (camera angles, lighting, etc.) before introducing 3D graphics into your applications.

Drew Robbins finished the meeting by transforming a dull and unwieldy application into a visually appealing and very user-friendly application without touching any of the underlying functionality of the code! Drew guided us through some of the new user controls that will be available to us as well as more XAML. The most impressive portion of the demo was when he took a basic listbox with the file paths of individual photos and changed it into a series of thumbnails that responded intuitively to mouse movement and clicks. In short, if you develop user interfaces, you want to spend some time with WPF.

Labels: ,

Friday, February 02, 2007

Drew Robbins Speaking at AADND

Drew Robbins, Developer Evangelist from Microsoft and the scary looking dude you see to the left, will be speaking at our next AADND meeting on February 14th. The topic is Windows Presentation Foundation (WPF) and if you haven't seen it in action, now is the time. I've also heard a rumor that Jennifer Marsman, Drew's co-Evangelist, will be doing a tutorial session. I don't have a bio for Jennifer yet - I'm sure she will be sending it soon, but here's the bio for Drew.

Drew Robbins is a Developer Evangelist for Microsoft in the Heartland District. Drew has over 12 years of experience using Microsoft products as both an IT Professional and Application Developer. Before joining Microsoft, Drew was already very active in the developer community on both a local and global level. He served in central Ohio as a Microsoft Regional Director (honorary Microsoft position), establishing a major user group and working in several enterprise accounts. Drew was also recognized as a Microsoft MVP for his role in community and expertise in Visual Studio and ASP.NET. Drew mobilized the global developer community through blogging websites that drove buzz and participation in conferences such as TechEd, PDC and DevDays. Drew is a regular presenter at local and regional events on Microsoft technology and development methodology.

Labels: ,

Thursday, January 11, 2007

AADND Success

Well, what can I say? AADND was a huge success. I haven't kept close track of the numbers in the past, but we were pretty close to a record turnout. Of course, when Matt Winkler is you speaker, there isn't much selling you have to do. And he certainly did deliver. Windows Workflow is really going to change the way you architect your applications and you need to know how. Doing so with Matt just makes the process a bit more clear and a lot more fun. If you were in attendance last night, you certainly know what I am talking about. Look for his slide deck at AADND later today.

Just a couple of "thank you"s before I end this post...

  • Dave Redding - worked hard on promoting this and has proven to be a strong leader.

  • Dave Baldwin - Keeps right on top of the website and has some fantastic - and very aggressive - ideas.

  • Dave Pease - Created the flyers that we posted around U of M and WCC. Defintely a future Board member.

  • Scott Zischerk - Yet another future board member. Great ideas.

  • Bill Wagner - He's the president - and my boss - who was there the for much needed advice.



and our Microsoft folks...

  • Josh Holmes - Thanks for booking Matt when you were still program chair for AADND and staying involved in the group

  • Drew Robbins - Thanks for the pizza!

  • Jennifer Marsman - Thanks for getting Matt to the meeting on time.

  • Gautam Reddy - We've only just begun using his expertise

Labels: ,

Wednesday, January 03, 2007

Matt Winkler Speaking at AADND on January 10

That's right. Matt Winkler, Technical Evangelist for Windows Workflow, will be speaking at AADND on January 10, 2007 in downtown Ann Arbor, MI. You've heard me prattle on and on about WCF, but WF is equally cool - maybe even more so. This is really going to change the way you architect your applications. Come and check it out.

A little about Matt...
Matt Winkler is the Technical Evangelist for Windows Workflow. He was born and raised in St. Louis, Missouri, home of Budweiser, the Cardinals and toasted ravioli. After college at Denison University, he returned to work for a consulting firm and a software development firm. For the last few years he has been focused on integration and workflow technologies, so he's very excited about Windows Workflow, and looking forward to finding many different cool uses for it.

Labels: ,

Sunday, December 31, 2006

WCF Webcast - Finally

Yes, my webcast is done. Hard to believe, I know. But in fairness, it was a bigger task than I originally thought. After a lot of time trying to figure out exactly what I wanted to discuss, I had to try to cut the content down to my 5 minute limit - a task that apparently was too much for me. One of the things that pained me to cut was an overview of some common exceptions and what to do to fix them. These are the basic exceptions that somebody new to WCF may not figure out right away. Things like mismatching bindings or calling the wrong port. I also didn't talk about the code generated by the svcutil.exe utility. Something I did leave in was the evil practice of defining endpoints and behaviors in code. Why take out the good and leave in the bad you ask? There are two reasons. First, I think most developers are more comfortable working with traditional languages as opposed to XML. Secondly, I think there will be a real appreciation for the configuration file when I begin refactoring. Of course, this pretty much sets me up for promising episode 2 sometime in the near future!

So here it is: a twelve minute introduction to creating a simple webservice using WCF while ignoring best practices.

Also, a special thank you goes out to Scott Zischerk for calling me out on NOT having my webcast done a lot earlier. Thaaaaanks, Scott!

WCF Webcast Episode 1

Labels: , ,

Wednesday, November 29, 2006

WCF Webcasts, Java and CodeMash

First off, I thought I was going to be able to jump right into my WCF webcasts that I promised, but it appears that I am going to have to put a little more thought into this. First off, I want to design my webcasts to be as short and focused as possible - hopefully five minutes or less. Why the limitation? I was listening to Mark Miller on an old episode of dotnetrocks (do yourself a favor and listen) talk about the great features we develop that are only ignored by the customer. Why do they ignore, you ask? Because customers don't know it's there and/or they don't know how to use it. One of his ideas to combat the problem was to was to include brief training videos no more than 5 minutes long in the help "infrastructure". I heard this and said, "hmmmmmmmmmmm....I know! I'm going to steal Miller's idea and tell everyone I came up with it"! Inject the evil scientist laugh here. All kidding aside, I think he brings up a great point for a couple of reasons. One, if you are new to a particular application, you will hit the help files and the internet a lot looking for very easy answers. I do not often find easy answers in help files. I do, however, seem to get a lot out of watching someone explain what they are doing while they are coding. As proof of this, I just recently listened to Miguel Castro talk about web controls on dotnetrocks AND watch similar content on dnrTV. The difference was amazing. I got so much more out of the dnrTV episodes (btw, this is no knock against dotnetrocks. I condider myself a loyal fan). Unfortunately, I can't watch dnrTV for an hour everytime I have a problem. Therefore, I feel very short, well-defined segments are far more helpful than hundreds of lines in a help file. I could be wrong here (or I suppose Mark Miller could be wrong), but I doubt it. Therefore, I'm looking I'm looking at the entirety of what I'm trying to develop before I begin. I'll keep you posted.

Last post, I was talking about Java. If you're one of the two people who read my blog, you'll know that I'm reading Thining in Java. I'm getting ready for CodeMash and want to be able to intelligently discuss platform differences - something I consider a shortcoming of mine. Well, I've read a couple hundred pages and I can tell you there is little difference at the superficial leve between Java and .NET. Makes sense, since Java was a bit of a model for .NET. One interesting point is that I feel I'm learning a lot about .NET by doing the examples in the book. Who would have thunk?

CodeMash – I&apos;ll be there!
Have you registerd for CodeMash yet? If not, WHAT ON EARTH ARE YOU WAITING FOR?!? Here is a conference that has Scott Guthrie, Neal Ford and Bruce Eckel lined up as keynote speakers, something few of us have thought could ever happen. Register now at www.codemash.org. You want to be part of this one.

Labels: , , ,