Friday was my last day at IONX, the first job I had out of school. IONX was a pretty cool place to work, not the ordinary kind of first job that some people get doing the "grunt" work that more senior programmers didn't want for themselves. It was a relatively small place, and though it's been growing quickly, I was still able to carve out a place for myself as a productive, influential, and respected programmer.
The time came eventually to start looking for something else. I started putting out resumes in a pretty non-committal way. Maybe one or two a month if I found really compelling job postings. For several months I hardly heard back from anybody. But this month, the rain began to pour. Ultimately I decided to take a position with Weblinc, an e-commerce company based in Philadelphia.
Starting on Monday I'll be taking the train to center-city Philadelphia every day, again. It's going to be a fun new adventure and I'm looking forward to getting started. I'll post more information about what exactly my new job entails when I learn a little bit more about it myself.
Showing posts with label Work. Show all posts
Showing posts with label Work. Show all posts
Saturday, October 23, 2010
Friday, July 30, 2010
Sic Semper VisualBasicus
Something I overheard today at work:
It still boggles my mind that so much code is written in VisualBasic.
We should hold a big VisualBasic conference, and once everybody is inside we gas the place.
It still boggles my mind that so much code is written in VisualBasic.
Labels:
VisualBasic,
Work
Thursday, July 29, 2010
Silverlight Website
Yesterday I mentioned that I'm writing a new web application with Silverlight. I also expressed a few misgivings about the current level of support for Silverlight in VisualStudio and other tools. Today, I'm going to talk a little bit about the design of this new website and some of the decisions that we made to arrive at this design.
Our current web application is written in ASP.NET/C# and uses a series of third-party plugin controls to add improved aesthetics, performance, and capabilities. This strategy works reasonably well, though I've personally found it to not be maintainable as-is. I've found that complexity is growing much more quickly than capability does, and that our limited development resources quickly get strained. This is especially true when we start running into impossible-to-debug errors in hundreds of lines of generated javascript. Our entire team has ground to a halt on more than one occasion while one intrepid developer suffered through long sessions of phone tech-support to resolve these kinds of issues.
If we were using a combination of PHP and JavaScript, with a comprehensive client-side framework like jQuery things might be a little different. But, we're not. That ship has long-since sailed and there is no going back now.
The fact is that my office is a C# house. All our developers know C#, all our projects are written in C#. Trying to switch our main web application to use PHP instead would require major retooling time and effort, retraining for several developers, lots of lost time and productivity, etc. C# is as good a language as any, and if we can get moving with the right tools and the right technologies it should work just as well as anything else.
The problem I have with ASP is that it doesn't run directly, it generates HTML, CSS, and JavaScript. The result is that the source of the actual page which the client receives bears only the vaguest resemblance to the code which the developer wrote. Find a bug somewhere in the CSS? Unhandled JavaScript exception? Unless it is painfully obvious where the problem is coming from, it might be impossible for anybody to trace that problem directly back to the offending ASP code. Producing a robust and portable solution may be even harder.
This is not to mention that there are major differences in JavaScript, HTML, and CSS implementations between browsers and there's no guarantee that anything you see on your development machine will look the same when the client gets it. I can guarantee that Microsoft tries hardest to make things look spiffy in Internet Explorer, but even then I have found some severe problems with ASP websites not rendering properly in various versions of IE. For modern browsers this usually isn't a huge problem anyway, but we deal with several clients who use IE6 by corporate mandate and refuse to update for "security concerns". Go figure.
[Side Note: If your IT personnel claim that upgrading from IE6 to something newer is a security concern, fire them. This is the first sign, and not a trivial one, that the person in charge of your IT department is incompetent.]
JavaScript differences between such a huge range of browsers is really a pretty serious concern. There's a reason why I like working with VMs, which provide a standard interface across multiple platforms. Parrot is my favorite, of course, but .NET/Mono earns a strong honorable mention too. The more we can write in a managed language like C#, and the less it gets converted to something less reliable, the better. Generated code is the enemy here, and HTML/CSS/JavaScript is really a terrible choice for target "language".
These are the reasons why, in a nutshell, that I picked Silverlight for the new website. Toolchain support is sophomoric at best, but it does give us what we need otherwise: We can write everything in C#, we don't have to worry about differences in rendering, performance, or capability between different browsers. Even the poor IE6 folks have a Silverlight plugin installed. We can leverage the strengths of our existing team too, which is deadline-friendly. We have a good opportunity here to mature with our tools, and I've already filed a few bug reports and sent in some feedback to Microsoft about some of the issues I've found. All we need now is to wait for service pack 1 without killing ourselves or each other.
The website requirements are a pretty nebulous beast, as I'm sure they are for any sufficiently-usable web application. Different customers all want to see different things and have different tools at their disposal. What we needed was a framework that would allow us to create a pluggable interface and support/enforce encapsulation and abstraction like any modern MVP application wants. To do all these things, we decided to use Prism. Prism is part framework and part "guidance" which provides tools, lessons, and examples to follow for building modular MVP or MVVM applications. Basically, it's a nice booster to make sure your team is following some modern best-practices when it comes to scalable and maintainable application design.
Like any methodology, adhering too strictly to MVP or MVVM design can put you in an uncomfortable place, but if you take the lessons to heart and use the tools that you need, I've found that it works out pretty well. One particular nit that I do have about it is that aggressive decoupling of your classes leads to referring to modules by name with strings, or System.Type objects, and you miss out on entire classes of analysis and error-detection tools that your compiler's type system would provide otherwise. "Be really careful" is a strategy that doesn't really work well in life and doesn't really work well in programming either. There's nothing worse than trying to track down an error which raises no compiler warnings and fails silently at runtime too without throwing an exception. Combine this with my inability to debug Silverlight from VisualStudio and I've run into a few situations where I almost pulled some hair out. Once I get my debugging issues sorted out this won't nearly be so much of a problem, but right now it makes for long days.
Our current web application is written in ASP.NET/C# and uses a series of third-party plugin controls to add improved aesthetics, performance, and capabilities. This strategy works reasonably well, though I've personally found it to not be maintainable as-is. I've found that complexity is growing much more quickly than capability does, and that our limited development resources quickly get strained. This is especially true when we start running into impossible-to-debug errors in hundreds of lines of generated javascript. Our entire team has ground to a halt on more than one occasion while one intrepid developer suffered through long sessions of phone tech-support to resolve these kinds of issues.
If we were using a combination of PHP and JavaScript, with a comprehensive client-side framework like jQuery things might be a little different. But, we're not. That ship has long-since sailed and there is no going back now.
The fact is that my office is a C# house. All our developers know C#, all our projects are written in C#. Trying to switch our main web application to use PHP instead would require major retooling time and effort, retraining for several developers, lots of lost time and productivity, etc. C# is as good a language as any, and if we can get moving with the right tools and the right technologies it should work just as well as anything else.
The problem I have with ASP is that it doesn't run directly, it generates HTML, CSS, and JavaScript. The result is that the source of the actual page which the client receives bears only the vaguest resemblance to the code which the developer wrote. Find a bug somewhere in the CSS? Unhandled JavaScript exception? Unless it is painfully obvious where the problem is coming from, it might be impossible for anybody to trace that problem directly back to the offending ASP code. Producing a robust and portable solution may be even harder.
This is not to mention that there are major differences in JavaScript, HTML, and CSS implementations between browsers and there's no guarantee that anything you see on your development machine will look the same when the client gets it. I can guarantee that Microsoft tries hardest to make things look spiffy in Internet Explorer, but even then I have found some severe problems with ASP websites not rendering properly in various versions of IE. For modern browsers this usually isn't a huge problem anyway, but we deal with several clients who use IE6 by corporate mandate and refuse to update for "security concerns". Go figure.
[Side Note: If your IT personnel claim that upgrading from IE6 to something newer is a security concern, fire them. This is the first sign, and not a trivial one, that the person in charge of your IT department is incompetent.]
JavaScript differences between such a huge range of browsers is really a pretty serious concern. There's a reason why I like working with VMs, which provide a standard interface across multiple platforms. Parrot is my favorite, of course, but .NET/Mono earns a strong honorable mention too. The more we can write in a managed language like C#, and the less it gets converted to something less reliable, the better. Generated code is the enemy here, and HTML/CSS/JavaScript is really a terrible choice for target "language".
These are the reasons why, in a nutshell, that I picked Silverlight for the new website. Toolchain support is sophomoric at best, but it does give us what we need otherwise: We can write everything in C#, we don't have to worry about differences in rendering, performance, or capability between different browsers. Even the poor IE6 folks have a Silverlight plugin installed. We can leverage the strengths of our existing team too, which is deadline-friendly. We have a good opportunity here to mature with our tools, and I've already filed a few bug reports and sent in some feedback to Microsoft about some of the issues I've found. All we need now is to wait for service pack 1 without killing ourselves or each other.
The website requirements are a pretty nebulous beast, as I'm sure they are for any sufficiently-usable web application. Different customers all want to see different things and have different tools at their disposal. What we needed was a framework that would allow us to create a pluggable interface and support/enforce encapsulation and abstraction like any modern MVP application wants. To do all these things, we decided to use Prism. Prism is part framework and part "guidance" which provides tools, lessons, and examples to follow for building modular MVP or MVVM applications. Basically, it's a nice booster to make sure your team is following some modern best-practices when it comes to scalable and maintainable application design.
Like any methodology, adhering too strictly to MVP or MVVM design can put you in an uncomfortable place, but if you take the lessons to heart and use the tools that you need, I've found that it works out pretty well. One particular nit that I do have about it is that aggressive decoupling of your classes leads to referring to modules by name with strings, or System.Type objects, and you miss out on entire classes of analysis and error-detection tools that your compiler's type system would provide otherwise. "Be really careful" is a strategy that doesn't really work well in life and doesn't really work well in programming either. There's nothing worse than trying to track down an error which raises no compiler warnings and fails silently at runtime too without throwing an exception. Combine this with my inability to debug Silverlight from VisualStudio and I've run into a few situations where I almost pulled some hair out. Once I get my debugging issues sorted out this won't nearly be so much of a problem, but right now it makes for long days.
Labels:
Prism,
Silverlight,
VisualStudio,
Work
Tuesday, July 27, 2010
VisualStudio 2010
The new web application at my work is going to be Silverlight-based, which gives me an opportunity to learn a fancy new technology and add another line of gibberish to my resume.
As anybody who's worked with Silverlight will tell you, VisualStudio 2008 really doesn't help you at all. I don't have many nice things to say about XAML, and VS2008 requires you to write it by hand. We could use Expression Blend, but without a paid license you're using a crippled product, and that doesn't make any sense when you already have an expensive license to VisualStudio. Luckily, the beautiful IT people got us licenses for VisualStudio 2010, which boasts massively-improved Silverlight support.
Notice that I said "Massively-improved", not "perfect" or even "good". Yes, VS2010 is head-and-shoulders above VS2008 in terms of Silverlight support. However, I'm having a hard time really appreciating those improvements in light of the other glaring deficiencies. And there are many deficiencies still.
In the marketing and documentation VisualStudio 2010 is sold as having "Silverlight support". What does that even mean? Yes there is a new WYSIWYG editor to help improve Silverlight GUI design which produces mostly-correct XAML code. It's far better than nothing, but I find it to still be ridiculously frustrating to do even simple operations. Working with grids is tiresome. Working with controls which need to dynamically size is even worse. I find myself several times an hour wishing I could use some CSS to add style information. I find myself wishing I could specify height in percent, instead of a fixed number, the ambiguous "Auto" or as a weighted ratio. None of these are even among the most damning criticisms I have.
The set of built-in controls available to the Silverlight developer is paltry at best. If you want to write anything more complicated than a tic-tac-toe game, you're going to need to download some kind of add-in or third party package. Even some of the most basic controls that a Windows developer has grown accustomed to in the past 20 years are missing with no replacements in sight. All the best documentation, even documentation from Microsoft, recommends you download the Silverlight Toolkit to get back some of these basics. You have to wander why some of these necessary and recommended controls weren't just included in the standard libraries.
Silverlight has support for several powerful graphical features like transforms, animations, storyboards, and projections, but no good ones are available by default. Get within 20 feet of PowerPoint and some knucklehead is going to abuse the star-wipe, but the basic Silverlight library doesn't even provide you with a basic wipe, fade, slide or expand/shrink. Combine that with the fact that VisualStudio2010 doesn't really provide you with any decent tools to create these things yourself, and you find a huge new source of frustration.
And I've left my biggest complaint for last: Debugging. Let me add some emphasis here for clarity: You cannot debug a Silverlight application in VisualStudio 2010 without downloading and installing a separate, and finicky, add-on. You cannot debug Silverlight applications, by default, in an IDE which boasts "Silverlight support". If you want to debug your Silverlight application (or do other advanced operations like "unit testing"), you need to download the Silverlight Tools for VisualStudio 2010 package. I can't even imagine why they wouldn't have included this functionality directly in VisualStudio itself, if every Silverlight developer is going to need to download and install it separately for even the most basic tasks. That is a decision that boggles the mind and leaves me completely flabbergasted.
But wait! The problems have not ended once you install those tools. If you install your add-ons in the wrong order, or pick the wrong settings in VisualStudio or even your browser, or unknowingly anger the gods of programming, you still won't be able to debug. I know, it happened to me. I haven't been able to set a breakpoint since I started this web application two days ago, and it is seriously hampering my coding mojo.
I like Silverlight, generally. The reliance on XAML is a pretty lousy and short-sighted design decision, in my opinion, but isn't a killer. You do get rich client-side applications without having to write them in ActionScript or Java. I wish that VisualStudio's touted "support" was a little bit more impressive and comprehensive. In short, I really hope that this platform and toolchain matures significantly in the coming years, because we have a growing web application that we're going to need to be expanding and maintaining for the foreseeable future.
As anybody who's worked with Silverlight will tell you, VisualStudio 2008 really doesn't help you at all. I don't have many nice things to say about XAML, and VS2008 requires you to write it by hand. We could use Expression Blend, but without a paid license you're using a crippled product, and that doesn't make any sense when you already have an expensive license to VisualStudio. Luckily, the beautiful IT people got us licenses for VisualStudio 2010, which boasts massively-improved Silverlight support.
Notice that I said "Massively-improved", not "perfect" or even "good". Yes, VS2010 is head-and-shoulders above VS2008 in terms of Silverlight support. However, I'm having a hard time really appreciating those improvements in light of the other glaring deficiencies. And there are many deficiencies still.
In the marketing and documentation VisualStudio 2010 is sold as having "Silverlight support". What does that even mean? Yes there is a new WYSIWYG editor to help improve Silverlight GUI design which produces mostly-correct XAML code. It's far better than nothing, but I find it to still be ridiculously frustrating to do even simple operations. Working with grids is tiresome. Working with controls which need to dynamically size is even worse. I find myself several times an hour wishing I could use some CSS to add style information. I find myself wishing I could specify height in percent, instead of a fixed number, the ambiguous "Auto" or as a weighted ratio. None of these are even among the most damning criticisms I have.
The set of built-in controls available to the Silverlight developer is paltry at best. If you want to write anything more complicated than a tic-tac-toe game, you're going to need to download some kind of add-in or third party package. Even some of the most basic controls that a Windows developer has grown accustomed to in the past 20 years are missing with no replacements in sight. All the best documentation, even documentation from Microsoft, recommends you download the Silverlight Toolkit to get back some of these basics. You have to wander why some of these necessary and recommended controls weren't just included in the standard libraries.
Silverlight has support for several powerful graphical features like transforms, animations, storyboards, and projections, but no good ones are available by default. Get within 20 feet of PowerPoint and some knucklehead is going to abuse the star-wipe, but the basic Silverlight library doesn't even provide you with a basic wipe, fade, slide or expand/shrink. Combine that with the fact that VisualStudio2010 doesn't really provide you with any decent tools to create these things yourself, and you find a huge new source of frustration.
And I've left my biggest complaint for last: Debugging. Let me add some emphasis here for clarity: You cannot debug a Silverlight application in VisualStudio 2010 without downloading and installing a separate, and finicky, add-on. You cannot debug Silverlight applications, by default, in an IDE which boasts "Silverlight support". If you want to debug your Silverlight application (or do other advanced operations like "unit testing"), you need to download the Silverlight Tools for VisualStudio 2010 package. I can't even imagine why they wouldn't have included this functionality directly in VisualStudio itself, if every Silverlight developer is going to need to download and install it separately for even the most basic tasks. That is a decision that boggles the mind and leaves me completely flabbergasted.
But wait! The problems have not ended once you install those tools. If you install your add-ons in the wrong order, or pick the wrong settings in VisualStudio or even your browser, or unknowingly anger the gods of programming, you still won't be able to debug. I know, it happened to me. I haven't been able to set a breakpoint since I started this web application two days ago, and it is seriously hampering my coding mojo.
I like Silverlight, generally. The reliance on XAML is a pretty lousy and short-sighted design decision, in my opinion, but isn't a killer. You do get rich client-side applications without having to write them in ActionScript or Java. I wish that VisualStudio's touted "support" was a little bit more impressive and comprehensive. In short, I really hope that this platform and toolchain matures significantly in the coming years, because we have a growing web application that we're going to need to be expanding and maintaining for the foreseeable future.
Labels:
Silverlight,
VisualStudio,
Work
Wednesday, February 10, 2010
So Bad It's Funny
At work I've been taking a program written by another engineer and trying to merge the functionality into a program that I've been writing. During this process, I have found some code so bad that it's both funny and depressing at the same time. Here is a great example:
[Update 10 Feb 2010: This code is C#]
...which is basically the long way to write:
I guess the original coder wanted to make double-sure that the two values were equal.
[Update 10 Feb 2010: This code is C#]
public bool CheckMsgValid(byte[] _myArray, int _myIdx) {
bool t;
t = ((_myArray[_myIdx] & 0x80) == 0x80) ? true : false;
return t;
}
...which is basically the long way to write:
public bool CheckMsgValid(byte[] b, int x) {
return b[x] & 0x80 != 0 ;
}
I guess the original coder wanted to make double-sure that the two values were equal.
Friday, July 24, 2009
Why IIS Has Poor Market Share
Well, this probably isn't the only reason why IIS has such poor market share, but it is certainly the reason why I won't be using IIS for my work.
The Setup
My computer at work was recently reformatted using a "Windows XP Pro SP2" installation CD. After the install, I updated (on recommendation from Microsoft's Windows Updater) to SP3. I did this immediately because of security concerns.
When I tried to install IIS to do some testing of websites and services that I've been developing, I was told that I needed to insert my "Windows XP Pro SP3" CD instead. I don't have an SP3 CD, just an SP2 one. Too bad, can't use that!
The Twist
So I do a Google search for "IIS", and then do a search for "Download IIS". Most of the results that pop up are forum and mailinglist posts from people having the same kind of problem that I am having. So I went to iis.net, a website that, I'm positive, must have a download link somewhere. So I click "Downloads", and can't find it. I click the link "Try IIS7", but that isn't it either. I search through the list of downloads for about 30 minutes before giving up in despair. If there is a download link to get IIS from this website, I can't find it. Well, I could find a trial download of Windows Server 2008 that came with IIS, but I'm not reformatting my computer again to install a trial version of the OS just so I can have the privilege of using IIS (and then being nagged forever about how I'm using a trial version and I need to purchase a legitimate license). There are some forms of obnoxiousness that I absolutely refuse to tolerate coming from my computer.
So I click on the "Chat live with a specialist" link, which insists that it's going to be a "live" person. A window opens up that says "Liveperson", and shows a picture of a live human female. I spend the next 10 minutes chatting with a bot. Actually, it could have been a person who was so heavily scripted and ignorant of their work that they failed the turing test completely. Here's an actual quote, to get a sense of what I mean, keep in mind that we are on Microsoft's iis.net website where every single page literally has a reference to ISS on it: "I see. To make sure we are on the same page, can you tell me what IIS is an acronym for?". "She" tells me that she can't be of any help (probably because "she" is just a bot) and gives me a phone number to call to get in touch with the sales manager. No thanks, I don't want to buy anything, especially when it's this much of a hassle.
The Punchline
So I'm not going to use IIS on my computer. I've given up on it. It's obviously too much of a hassle, and the benefit is only that I'll be able to develop and properly test IIS-based websites locally. When we start designing our next generation product line and developing our next generation platform, I'm going to suggest to my boss that we use a web server that we will be able to get easily and use for proper testing: Apache.
The Setup
My computer at work was recently reformatted using a "Windows XP Pro SP2" installation CD. After the install, I updated (on recommendation from Microsoft's Windows Updater) to SP3. I did this immediately because of security concerns.
When I tried to install IIS to do some testing of websites and services that I've been developing, I was told that I needed to insert my "Windows XP Pro SP3" CD instead. I don't have an SP3 CD, just an SP2 one. Too bad, can't use that!
The Twist
So I do a Google search for "IIS", and then do a search for "Download IIS". Most of the results that pop up are forum and mailinglist posts from people having the same kind of problem that I am having. So I went to iis.net, a website that, I'm positive, must have a download link somewhere. So I click "Downloads", and can't find it. I click the link "Try IIS7", but that isn't it either. I search through the list of downloads for about 30 minutes before giving up in despair. If there is a download link to get IIS from this website, I can't find it. Well, I could find a trial download of Windows Server 2008 that came with IIS, but I'm not reformatting my computer again to install a trial version of the OS just so I can have the privilege of using IIS (and then being nagged forever about how I'm using a trial version and I need to purchase a legitimate license). There are some forms of obnoxiousness that I absolutely refuse to tolerate coming from my computer.
So I click on the "Chat live with a specialist" link, which insists that it's going to be a "live" person. A window opens up that says "Liveperson", and shows a picture of a live human female. I spend the next 10 minutes chatting with a bot. Actually, it could have been a person who was so heavily scripted and ignorant of their work that they failed the turing test completely. Here's an actual quote, to get a sense of what I mean, keep in mind that we are on Microsoft's iis.net website where every single page literally has a reference to ISS on it: "I see. To make sure we are on the same page, can you tell me what IIS is an acronym for?". "She" tells me that she can't be of any help (probably because "she" is just a bot) and gives me a phone number to call to get in touch with the sales manager. No thanks, I don't want to buy anything, especially when it's this much of a hassle.
The Punchline
So I'm not going to use IIS on my computer. I've given up on it. It's obviously too much of a hassle, and the benefit is only that I'll be able to develop and properly test IIS-based websites locally. When we start designing our next generation product line and developing our next generation platform, I'm going to suggest to my boss that we use a web server that we will be able to get easily and use for proper testing: Apache.
Friday, July 10, 2009
Python, Trac, and Agile
Haven't blogged in a few days, and it's not because I've been burned out from my blogging sprint two weeks ago like some people suggested. I've been under the weather and have had a lot of other things going on that required my attention. I actually have drafted several posts, just haven't published any of them for a variety of reasons. I have been getting good feedback still from several of my older posts, so that's nice to see.
At work we've been trying to become more Agile, and my boss has started using the curious words "agile" and "scrum" more frequently. We've had a very small team here for a while and our development processes have been very ad hoc and personalized. When your "team" is one person, and each "department" is one or two people, it's hard to say we need to implement particular methodologies to help promote better team development. Of course, as we grow the need for more standardized methodologies is becoming clear.
We set up a development server with SVN, Trac, and MediaWiki for our team to use. We had been using DynamSoft's Visual Source Anywhere Hosted service for our source control, which worked reasonably well when our team was smaller. However, as we grew larger and as our network infrastructure became more capable, it was less and less of an attractive option then running our own SVN repository on one of our development servers. We were also using DynamSoft's Issue Tracking Anywhere, which I never liked personally and found to be far less helpful to us then a free alternative like Trac or Bugzilla would be.
So I created installed SVN and created the repository (easy), installed XAMPP (easy) and MediaWiki (very easy). Then, it was time to install Trac. Saying that the installation (and ongoing configuration and maintenance) was difficult is an understatement. Welcome to dependency hell. Lasciate ogni speranza voi chi entrate.
XAMPP installed Apache 2.2, and I picked up the "latest" SVN (which is what the Trac documentation specified), which happens to be 1.6.3. I'm running this whole monstrous software stack on Windows Server. And don't tell me to use Linux instead, that isn't an acceptable or available solution in this case. I first tried installing everything on the existing IIS server, but that was even worse of a nightmare. So, I have made some concessions by running Apache instead (although the IT guys aren't thrilled about having one special-case Apache server in a whole network of all IIS servers, but they are going to deal with it).
Between the core Python distribution (2.5), modpython (3.3.1), the python SVN bindings, and Trac, there are very very few setups that I can use to ensure compatibility. Combine this with the fact that I have the newest SVN (1.6.3 at the time) and the newest Apache (2.2), and there are very few configurations that seem to work. Following the installation instructions for Trac alone give me huge headaches because the versions specified in the installation instructions don't work together, and that's straight out of the Trac documentation.
I've been able to get Trac o.11 installed and working but I have not been able to install any of the plugins we are interested in. Apparently most of the newest plugins expect Trac 0.11 to have Genshi 0.6, but my installation manages only to have Genshi 0.5.2. I tried to update, but Genshi doesn't appear to be compatible with Python 2.5 or something, and that failed. Too many error messages that I've seen over the course of a week of trying now, I can't remember what they all are specifically.
We already have Trac installed and in use by our team, so I'm not switching now to use Bugzilla or something different. However, as my first real experience with the Python ecosystem I am severely unimpressed and even disheartened. It is far more difficult getting these kinds of things installed then it should be. I don't deny that I've been a bit spoiled by Perls CPAN, and Ubuntus apt-get repository system, things that just work when I want them to.
The documentation I have seen (when any even exists) and the "help" I've been able to get from people is sub-par at best. Maybe that's the norm in the Python world or the open source world in general, and that's very upsetting to think about. It is all the more reason why I believe so strongly in the Parrot concepts of interoperability and platform abstraction.
At work we've been trying to become more Agile, and my boss has started using the curious words "agile" and "scrum" more frequently. We've had a very small team here for a while and our development processes have been very ad hoc and personalized. When your "team" is one person, and each "department" is one or two people, it's hard to say we need to implement particular methodologies to help promote better team development. Of course, as we grow the need for more standardized methodologies is becoming clear.
We set up a development server with SVN, Trac, and MediaWiki for our team to use. We had been using DynamSoft's Visual Source Anywhere Hosted service for our source control, which worked reasonably well when our team was smaller. However, as we grew larger and as our network infrastructure became more capable, it was less and less of an attractive option then running our own SVN repository on one of our development servers. We were also using DynamSoft's Issue Tracking Anywhere, which I never liked personally and found to be far less helpful to us then a free alternative like Trac or Bugzilla would be.
So I created installed SVN and created the repository (easy), installed XAMPP (easy) and MediaWiki (very easy). Then, it was time to install Trac. Saying that the installation (and ongoing configuration and maintenance) was difficult is an understatement. Welcome to dependency hell. Lasciate ogni speranza voi chi entrate.
XAMPP installed Apache 2.2, and I picked up the "latest" SVN (which is what the Trac documentation specified), which happens to be 1.6.3. I'm running this whole monstrous software stack on Windows Server. And don't tell me to use Linux instead, that isn't an acceptable or available solution in this case. I first tried installing everything on the existing IIS server, but that was even worse of a nightmare. So, I have made some concessions by running Apache instead (although the IT guys aren't thrilled about having one special-case Apache server in a whole network of all IIS servers, but they are going to deal with it).
Between the core Python distribution (2.5), modpython (3.3.1), the python SVN bindings, and Trac, there are very very few setups that I can use to ensure compatibility. Combine this with the fact that I have the newest SVN (1.6.3 at the time) and the newest Apache (2.2), and there are very few configurations that seem to work. Following the installation instructions for Trac alone give me huge headaches because the versions specified in the installation instructions don't work together, and that's straight out of the Trac documentation.
I've been able to get Trac o.11 installed and working but I have not been able to install any of the plugins we are interested in. Apparently most of the newest plugins expect Trac 0.11 to have Genshi 0.6, but my installation manages only to have Genshi 0.5.2. I tried to update, but Genshi doesn't appear to be compatible with Python 2.5 or something, and that failed. Too many error messages that I've seen over the course of a week of trying now, I can't remember what they all are specifically.
We already have Trac installed and in use by our team, so I'm not switching now to use Bugzilla or something different. However, as my first real experience with the Python ecosystem I am severely unimpressed and even disheartened. It is far more difficult getting these kinds of things installed then it should be. I don't deny that I've been a bit spoiled by Perls CPAN, and Ubuntus apt-get repository system, things that just work when I want them to.
The documentation I have seen (when any even exists) and the "help" I've been able to get from people is sub-par at best. Maybe that's the norm in the Python world or the open source world in general, and that's very upsetting to think about. It is all the more reason why I believe so strongly in the Parrot concepts of interoperability and platform abstraction.
Monday, May 11, 2009
Reading Data from the Serial Port
At work I'm building a program that is, in part, a serial port console like HyperTerminal. It's not a pure drop-in replacement, we have some specific requirements that HyperTerminal didn't quite meet. However, a lot of the port-handling logic in my program could probably be repurposed for creating a more faithful drop-in replacement if the need arose.
The biggest problem for me at the beginning was deciding how to read data from the port. Obviously, we can't do the reading synchronously, in the case of a TTY-like program that just doesn't make any sense. I had two real options for asychronous operation:
On top of all those reasons, as if I need another one, I feel like using an explicitly-managed thread here is a particularly inelegant solution. In short, I decided to use the DataReceived event handler to do my port reading (when I put my port into asynchronous read mode, that is).
That question out of the way, I needed to decide how to do input buffering. Do I buffer by line (SerialPort.ReadLine), "buffer" by character (SerialPort.ReadChar), or do I not buffer (SerialPort.ReadExisting)? On the one hand I need to support both buffered and non-buffered input. On the other hand I don't want to be stacking up DataReceived events with Timeout events endlessly, because that could create a stability problem.
My design goes as follows: I use the DataReceived event handler to signal me when data is ready. From within the handler I use SerialPort.ReadExisting to read the incoming data into a buffer, and from there slice and dice the input into the forms needed by modules higher up in my program. I admit that this may not be the most attractive or elegant code I have ever written, but it has demonstrated itself to be very performant and robust solution for my needs:
The function "ReadHandler" takes two arguments: The string value that's read (without carriage return or linefeed characters) and a boolean value indicating whether the given string is followed by a newline or not. Further up the call chain the display function will take that information to display timestamps and do other per-line formatting fanciness. It's worth noticing that since we are calling from within an event handler, ReadHandler probably needs to call BeginInvoke to pass it's incoming data to the GUI (that's what my code does, anyway).
The way I lock the readBuffer repeatedly was something that I figured out later. When data is incoming quickly (like 115200 baud or higher) we can get multiple DataReceived events being triggered and stacking up if we lock through the entire function. This can cause noticeable program slowdowns when a number of event handlers acquire the lock subsequently. Instead, I lock smaller parts of the code and let additional handler instances run concurrently but with no input. Throughput performance is better in these cases, and is not noticeably different otherwise.
So that's my implementation of a buffered asynchronous serial port reader in C#. It's not perfect, but it gets the job done, has pretty good throughput, and is relatively fault tolerant.
The biggest problem for me at the beginning was deciding how to read data from the port. Obviously, we can't do the reading synchronously, in the case of a TTY-like program that just doesn't make any sense. I had two real options for asychronous operation:
- Create a worker thread that reads from the port, sleeps for a certain timeout, and then repeats.
- Use the DataReceived handler on the SerialPort object to automatically call a callback when incoming data is received.
On top of all those reasons, as if I need another one, I feel like using an explicitly-managed thread here is a particularly inelegant solution. In short, I decided to use the DataReceived event handler to do my port reading (when I put my port into asynchronous read mode, that is).
That question out of the way, I needed to decide how to do input buffering. Do I buffer by line (SerialPort.ReadLine), "buffer" by character (SerialPort.ReadChar), or do I not buffer (SerialPort.ReadExisting)? On the one hand I need to support both buffered and non-buffered input. On the other hand I don't want to be stacking up DataReceived events with Timeout events endlessly, because that could create a stability problem.
My design goes as follows: I use the DataReceived event handler to signal me when data is ready. From within the handler I use SerialPort.ReadExisting to read the incoming data into a buffer, and from there slice and dice the input into the forms needed by modules higher up in my program. I admit that this may not be the most attractive or elegant code I have ever written, but it has demonstrated itself to be very performant and robust solution for my needs:
private string readBuffer;
private SerialPort port;
private bool unBuffNeedNewline = false;
private void InitPort()
{
this.port = new SerialPort();
this.port.DataReceived += new SerialDataReceivedHandler(DataReceiver_Handler);
}
private void DataReceiver_Handler(object sender, SerialDataReceivedEventArgs e)
{
if(this.bufferMode == ConnectionHelpers.ReadBuffering.LineBuffered)
this.DataReceiverLineBuffered();
else
this.DataReceiverCharBuffered();
}
private void DataReceiverLineBuffered()
{
try {
string x;
lock(this.readBuffer) {
x = this.readBuffer + this.port.ReadExisting();
}
char[] delim = new char[2] {'\n', '\r'};
while(x.Length > 1 && (x.Contains("\n") || x.Contains("\r"))) {
String[] ary = x.Split(delim, 2);
this.ReadHandler(ary[0], true);
x = ary[1] + this.port.ReadExisting();
}
lock(this.readBuffer) {
this.readBuffer = x;
}
} catch(Exception e) {
this.StatusReporter("Serial Read Error: " + e.ToString());
}
}
private void DataReceiverCharBuffered()
{
try {
string x;
lock(this.readBuffer) {
x = this.readBuffer + this.port.ReadExisting();
}
while(x.Length >= 1) {
string c = x.Substring(0, 1);
if(c == "\r" || c == "\n") {
this.unBuffNeedNewline = true;
x = x.Substring(1) + this.port.ReadExisting();
}
else if(this.unBuffNeedNewline) {
this.ReadHandler("", true);
this.unBuffNeedNewline = false;
} else {
this.ReadHandler(c, false);
x = x.Substring(1) + this.port.ReadExisting();
}
}
} catch(Exception e) {
this.StatusReporter("Serial Read Error: " + e.ToString());
}
}
The function "ReadHandler" takes two arguments: The string value that's read (without carriage return or linefeed characters) and a boolean value indicating whether the given string is followed by a newline or not. Further up the call chain the display function will take that information to display timestamps and do other per-line formatting fanciness. It's worth noticing that since we are calling from within an event handler, ReadHandler probably needs to call BeginInvoke to pass it's incoming data to the GUI (that's what my code does, anyway).
The way I lock the readBuffer repeatedly was something that I figured out later. When data is incoming quickly (like 115200 baud or higher) we can get multiple DataReceived events being triggered and stacking up if we lock through the entire function. This can cause noticeable program slowdowns when a number of event handlers acquire the lock subsequently. Instead, I lock smaller parts of the code and let additional handler instances run concurrently but with no input. Throughput performance is better in these cases, and is not noticeably different otherwise.
So that's my implementation of a buffered asynchronous serial port reader in C#. It's not perfect, but it gets the job done, has pretty good throughput, and is relatively fault tolerant.
Friday, May 8, 2009
Inheritable Menus in C#
I've been coding a program at work that is supposed to interface with and control a wireless sensor network. It's a heterogeneous network where each node may be one of several different types with different capabilities, represented internally by child classes of an abstract "WirelessSensorNode" parent class. To keep track of things, I display all the nodes and their children (things, including other nodes that connect through them) in a TreeView.
The problem I ran into was trying to create a context menu that would be displayed when I right-clicked on a TreeNode in the tree. Because each node class was different, I needed to display slightly different menus for each. I started the naive way, trying to create a new ContextMenuStrip item for each different class, and I ended up with a huge messy piece of logic like this:
And each menu, because there were some options common to all nodes, needed to contain some duplicate logic. This was, in short, a mess and extending this system to add new node types (and therefore new menus) was a real pain. What I really wanted to do was something like this, and leave the logic of menu building to the classes themselves:
So I decided instead to fix this system up yesterday to do the right thing in a better and more encapsulated way. The node classes themselves know what menu items they are capable of showing, my GUI should not be in charge of figuring that information out. So, I added this code to create a new attribute type, ContextMenuHandler for methods in a class, and a routine to read all methods with this attribute and add them to a menu:
And I added this code into the abstract parent class:
Not a whole lot of code to write for the flexibility that the system gives me. For people who aren't familiar with attributes, they are metadata items that can be added to methods (or other things) and can be examined at runtime using reflection. With this system, to add a new item to the menu of a particular class, I only need to create a new private method in that class with the ContextMenuHandler attribute:
No need to "install" the new menu item anywhere, the simple existance of this method in the class will enable the item to be shown in that menu. This is great for encapsulation because I don't want to be having to modify all sorts of existing code, especially not unrelated existing code, every time I want to add an option to my right-click menu. Plus, it gives me the ability to inherit menu items from the parent class into the menus of the child types, without having to write code in each child class to duplicate them!
There are some limitations to this method, obviously my class hierarchy is only 2-levels deep so this method as-is doesn't extend to arbitrarily deep class hierarchies. I'm sure it could be extended to do that with a little bit more System.Reflection magic, but I don't need to do it so I'm not going to spend the time. Despite the limitations my goals were met: context menus are inherited between classes, and I can edit/expand menus without having to modify all sorts of existing, working code.
The problem I ran into was trying to create a context menu that would be displayed when I right-clicked on a TreeNode in the tree. Because each node class was different, I needed to display slightly different menus for each. I started the naive way, trying to create a new ContextMenuStrip item for each different class, and I ended up with a huge messy piece of logic like this:
object o = myTreeView.SelectedNode.Tag;
if(o is NodeType1) menu1.Show();
else if(o is NodeType2) menu2.Show();
else if(o is NodeType3) menu3.Show();
...
And each menu, because there were some options common to all nodes, needed to contain some duplicate logic. This was, in short, a mess and extending this system to add new node types (and therefore new menus) was a real pain. What I really wanted to do was something like this, and leave the logic of menu building to the classes themselves:
WirelessSensorNode n = (WirelessSensorNode)myTreeView.SelectedNode.Tag;
ContextMenuStrip menu = n.GetContextMenu();
if(menu != null) menu.Show();
So I decided instead to fix this system up yesterday to do the right thing in a better and more encapsulated way. The node classes themselves know what menu items they are capable of showing, my GUI should not be in charge of figuring that information out. So, I added this code to create a new attribute type, ContextMenuHandler for methods in a class, and a routine to read all methods with this attribute and add them to a menu:
[AttributeUsage(AttributeTargets.Method, AllowMultiple=true)]
public class ContextMenuHandler : Attribute
{
public string name;
public ContextMenuHandler(string name)
{
this.name = name;
}
}
public static void AddContextMenuHandlers(System.Type c, object parent, ContextMenuStrip menu)
{
BindingFlags flags = BindingFlags.NonPublic | BindingFlags.DeclaredOnly |
BindingFlags.Instance;
foreach (MethodInfo method in c.GetMethods(flags)) {
foreach(object attribute in method.GetCustomAttributes(
typeof(ContextMenuHandler), false)) {
string name = ((ContextMenuHandler)attribute).name;
menu.Items.Add(new ToolStripMenuItem(name, null, new EventHandler(
delegate(object o, EventArgs e) {
method.Invoke(parent, null);
}
)));
}
}
}
And I added this code into the abstract parent class:
public virtual ContextMenuStrip GetContextMenu()
{
ContextMenuStrip menu = new ContextMenuStrip();
Helpers.AddContextMenuHandlers(typeof(WirelessSensorNode), this, menu);
Helpers.AddContextMenuHandlers(this.GetType(), this, menu);
return menu;
}
Not a whole lot of code to write for the flexibility that the system gives me. For people who aren't familiar with attributes, they are metadata items that can be added to methods (or other things) and can be examined at runtime using reflection. With this system, to add a new item to the menu of a particular class, I only need to create a new private method in that class with the ContextMenuHandler attribute:
[ContextMenuHandler("Menu Item 1")]
private void Menu_Item_1_ContextMenuHandler()
{
MessageBox.Show("You clicked 'Menu Item 1'");
}No need to "install" the new menu item anywhere, the simple existance of this method in the class will enable the item to be shown in that menu. This is great for encapsulation because I don't want to be having to modify all sorts of existing code, especially not unrelated existing code, every time I want to add an option to my right-click menu. Plus, it gives me the ability to inherit menu items from the parent class into the menus of the child types, without having to write code in each child class to duplicate them!
There are some limitations to this method, obviously my class hierarchy is only 2-levels deep so this method as-is doesn't extend to arbitrarily deep class hierarchies. I'm sure it could be extended to do that with a little bit more System.Reflection magic, but I don't need to do it so I'm not going to spend the time. Despite the limitations my goals were met: context menus are inherited between classes, and I can edit/expand menus without having to modify all sorts of existing, working code.
Subscribe to:
Posts (Atom)
