mgroves

Know your InterOp 3: Rich Text Editor

This is the last of the InterOp posts. Just a brief word on the "why", since I keep getting that question :)

I would not recommend InterOp as a first choice for writing a feature, or probably even a second choice. However, there are certain IT shops that have a fear of 3rd party components (they've been burned before, or have NIH syndrome, etc) or a mandate against using OSS. Writing our own spell checker or rich text editor can be very time consuming, so if InterOp is on the table, it's a viable alternative to writing it yourself. However, InterOp can be a deployment headache, unless you know that every user will have Office, and will have the same version. Okay, on with the show.

I was tasked with putting a rich text editor into a WinForms app, to handle the editing of email body templates. I was actually pretty shocked to find that there aren't really any decent open source or free RTEs for WinForms (at least that I could find). I briefly toyed with putting TinyMCE into a webbrowser control, but after reading a few blog posts, I decided to give InterOp a whirl and use the Trident (MSHTML) engine to be a rich text editor.

The idea is basically to use a WebBrowser control, set the 'document' in that control to 'edit mode' and voila, HTML rich text editor. Then you can program buttons to send 'commands' to the document, such as 'bold', 'italic', 'create link', etc. I won't post a code snippet here, because it's a relatively big hunk of code. Instead, I created an open source project called YARTE, or "Yet Another Rich Text Editor". I've tried to make it easy enough to use right out of the box, but extensible enough to add in custom functionality when necessary.

yarte_screenshot.png

So that wraps it up for InterOp, for now. These InterOp posts were born out of necessity and experience. Not because I'm an InterOp nut or a WinForms fan (because I am neither), but in the hopes that I can help developers in similar situations to the one I was in.

Keeping your computer secure

If you're like me and you don't have an IT department for your home network with rigorous security standards, you need to be even more vigilant when it comes to security, because you have no one to blame but yourself.

I've been using Secunia PSI (Personal Software Inspector) for some time now, and I've found it to be an excellent product for identifying out-of-date and insecure programs. Not only does it identify programs that need updated, but also how to update them, how to patch them, and even specific forum threads if I have a problem getting the update to take. It handles insecure, end-of-life, and even browser security. In "advanced" mode, I can see at a glance what needs updating, how serious the threat is, links to patches/updates, and links to the forum thread:

secunia_screenshot_smaller.jpg

(Note that screenshot was taken before I had run Windows Update on a new box).

It's always surprising to me what Secunia is able to find that I wouldn't have found on my own. For instance, PhpStorm (an excellent PHP IDE, by the way) comes with a copy of Java (JRE) for convenience, but the JRE gets updated frequently and PhpStorm doesn't update the JRE on its own. I had no idea the JRE was there until Secunia found it and told me it was out of date and a 4/5 threat rating. Simple solution: delete the outdated JRE and PhpStorm was able to find the updated version on my system with no problem.

Project Euler 22, 23, 24, 25, 26, and 27

Problem 22 was pretty straightforward; the problem description lays out the algorithm. One elegant piece of Linq was: word.Sum(c => c - ('A' - 1)), which sums up each letter score of the word nice and compactly.

Problem 23 - given the upper and lower limits of all possible abundant sums, this problem was, again, straightforward given the algorithm description. The toughest part was getting it performant, which is why I used a lookup collection for the IsAbundant method. At this point, my MathHelper class is coming in very handy, so I may just release it as its own project one day (though I'm sure there are many other equally good Math libraries for .NET).

Problem 24 - I did solve this problem, but my solution was not fast enough. Once I got the answer, I looked to see how other Eulers were doing it. So, for this class, I have both my solution and the more correct, "Fast" solution in the code. I think later on, I eventually created a permutation class, so I may need to revisit this problem with that class.

Problem 25 - Another easy one with BigInteger. I used a KeyValuePair because I was curious to see the actual number in the sequence, not just the index.

Problem 26 - This one took a lot of research and thinking. I spent a lot time reading about Cyclic numbers and Primitive roots. The solution feels like kinda a cheat to me, but I really don't see any way around it since "No simple general formula to compute primitive roots modulo n is known". Fortunately, Wikipedia lists just enough of them for me to solve the problem.

Problem 27 - I came up with a handy Quadratic class for this problem. I think in this case, the problem sounds pretty complex, but I broke it down into individual parts the best I could, and everything fit pretty well together. This is also a good strategy if you are having performance issues, as it will be easier for a profiler to point out where exactly the bottleneck is (hint: it's almost never where you think).

As always, you can view my code at CodePlex – feel free to submit criticisms/comments/patches there, or use the framework for your own Project Euler solution.

Know your InterOp 2: Sending email via Outlook

This is a much shorter example of using InterOp. In this case, the requirement was to send an email via Outlook so that the user would have the email in their "sent" folder, as well as receive any "replies" at their address.

Ultimately, I ended up using Exchange services, but here's my first attempt to fulfill the requirements using InterOp:

Very, very simple. Just drop this class in and call the SendEmail method on it. Note that depending on security setup, the user may see a "warning" message with a skippable countdown. Also note that you really shouldn't use this for sending more than 1 or 2 messages at a time, especially if that countdown appears, because it will be a very annoying user experience.

Know your InterOp 1: Spell checking

Being a web developer for most of my career, I haven't had much of an opportunity to use InterOp (i.e. API calls to Microsoft Office to provide functionality to another app). But as fate would have it, I've been working on a WinForms app as part of a project I'm on now, and I've chosen to use some InterOp features instead of a) reinventing the wheel, or b) using some other 3rd party component. There are some drawbacks to using InterOp, mainly that you have to have Office installed on any computer that the software is deployed to. The other main drawback is that you need to use COM for InterOp, which means the APIs can be very confusing, inconsistent, obfuscated, etc.

So I've decided to share what I've learn. I've done 3 major InterOp-dependent features: a spell checker, an HTML RTE, and an Outlook email sender. Here's the code for the spell checker:

I hope the code I've written makes it easier to understand than just plain InterOp calls, but here are some notes that might help:

1. Missing.Value. If you use InterOp, get used to this (unless you are using .NET 4). COM APIs were intended for languages that have optional parameter features (like VB). C# did not get that until the .NET 4 release. So, in C#, you have to put something down for each parameter.

2. I hope you don't mind my use of KeyValuePair. Again, if this were .NET 4, I'd probably use Tuple. I didn't really want to create a whole other class just for a private method, so I used KeyValuePair, even though I totally ignore the semantics of 'key' and 'value'. It's basically just a lazy way to have two return values. Feel free to adjust if it bothers you.

3. This code actually opens up Microsoft Word, puts text into a new Word document, runs spell checker on it, returns the updated text, and then closes Word. The user won't see the Word document, just the spell checker window, but be aware that Word is still being opened! If you don't close the Word document, then Word stays loaded, which could cause problems for normal use of Word later.

So, InterOp can seem a little strange, but often it can provide value to an application very quickly. A spell checker feature without InterOp would basically mean using Aspell to do the checking, and probably writing your own spell-checking UI.

PHP doesn't suck

I was cleaning out my Twitter favorites today. (I generally use my Twitter favorites as a 'bookmark' or a 'read this later' device). Anyway, I came across this tweet:

Jeff Atwood tweeting 'god I hate my code. It's terrible. AWFUL. Could be worse, though. Could be PHP.'

This got me a little riled up.

First, the sentiment that his code sucks is one that I can totally sympathize with. I'm very insecure about the code that I write, and I always see room for improvement. I'd refactor and refactor forever given the chance. So, it says something that the creator and developer of one of the most popular and (I think) well-crafted sites on the web (stackoverflow.com) even feels insecure about his code (which I'm sure is much better than he thinks).

Second, Atwood is one of the most outspoken PHP critics on the web. He does understand that building a compelling app is more important than the language it's written in, but his hatred of PHP still endures.

I'm here to say that PHP, as a language, does not suck. It has flaws, yes, but it is a real, viable language. Here are the things that I think makes PHP an excellent choice for building your next web app:

PHP is a language that is easy to learn. (This is also a downside). Any schmuck can start writing a web app in minutes with some cheap hosting and a text editor. This means value can be delivered very quickly (something that I'm sure Joel Spolsky appreciates).

PHP is arguably the most well-documented and completely documented programming language. The documentation available at php.net is nothing short of astounding. Each function/class has a description, parameters, examples, 'see also' links, not to mention a comment thread going back years with examples and tips.

PHP is popular and open source, and therefore it's a language that is constantly adapting and improving. This can also be a downside: naming conventions and best practices aren't 100% consistent, stuff gets deprecated, and some people aren't comfortable with that. Totally understandable.

PHP is a dynamic language with loose types. This means it can be very powerful, and sometimes very tricky. Some people aren't comfortable with this. I'm not even super-comfortable with it myself. By the way, another language that can be polarizing, JavaScript, is the same way: dynamic language with loose types. Coincidence?

There are great, mature frameworks and platforms for PHP (CakePHP and Wordpress, for instance), which I've found can be very helpful for reducing the downsides of PHP and magnifying the positives.

So that's my case for PHP. I don't think it deserves nearly all the crap it gets, and I think it's one of the top used languages in the world for good reason.

Project Euler 18, 67, 19, 20, 21

I spent a lot of time thinking about problem 18.  I knew that a brute-force solution might work, but as the problem states, I would have to face a larger version later on, so it would be in my best interest to write a solution that could handle a larger set.  The trick to problem 18 (and 67) is to think from the bottom-up, instead of the top-down.  Given a three-number pyramid, it’s easy to see that the high sum path depends entirely on the larger of the two bottom numbers.  Once you know that, just work your way up the pyramid, two rows at a time.  The rest of the class is just parsing and setup code.

Problem 19 is stupidly easy using the DateTime class that .NET provides.  I mean, it was just so trivial it’s barely worth mentioning.

Problem 20 would take a lot more thinking and work, were it not for the BigInteger class in .NET 4.  Since I have that available, I just made a Factorial method and a method to parse out a string into digits and sum them up.

I was stuck on Problem 21 for a bit.  Note that I was getting to problem 21 soon after I finally got problem 11 solved.   The main block I had on problem 21 was that I was just overthinking it.  The answer was very simple once I just broke it up into a series of simple steps—a nice, elegant solution emerged.

I was at a “Code and Coffee” session when I solved problem 21.  I had time left, so I paired up to solved problem 22.  This solution was very concise to express with Linq.  The crux of the problem was figuring out a good way to get a score for each letter.  It turns out the syntax is very similar to C++ [c - (‘A’ – 1) was all it took to score a single letter].  Thanks to the power of Linq, a string can be viewed as a collection of characters, and thus the ‘Sum’ extension method works on it.

As always, you can view my code at CodePlex – feel free to submit criticisms/comments/patches there, or use the framework for your own Project Euler solution.

Coke vs Coke

So maybe you’ve heard that Mexican Coke is made with “real” sugar (i.e. cane sugar), unlike Coke from the USA, which is made with evil, corporate sugar (i.e. corn syrup).  Mexicans who drink USA Coke often claim that it’s not as good as Mexican Coke, and older people from the US claim that Mexican Coke is the Coke that “they remember” from the pre-government-meddling-in-sugar era.  Go check out Snopes or Google for more background about the whole ridiculous controversy.

I’m not interested in any of the political nonsense (though I am against corn subsidies and sugar tariffs/quotas) as much as I’m interested in Coke itself: I drink a lot of Coke.  A lot.  Just ask anyone I know, and the first thing they’ll mention about me is their concern for the abusive amounts of Coke that I drink.  Between this word and the last period, I just drank some.  It’s a relatively large part of my dietary life, so naturally, I’m interested in all kinds of Coke lore, and even the promise of a better Coke from below the border.

One day, bottles of Mexican Coke showed up in the convenience store in the lobby of the office where I work.  In the interest of science, I bought 6 of them.  I drank a few, and put a few in the fridge for later testing.  I wanted to do a taste test to see if I could tell the difference, and which I preferred.  Here is the science:

Question: What’s the big deal about Mexican Coke and real sugar?

Background Research: See above.  Additionally, I have tried some other drinks (namely Hank’s Root Beer) made with cane sugar, and found them to be very tasty.

Hypothesis: Despite all the context I’ve mentioned, I was skeptical that I could tell the difference.

US Coke and Mexican Coke

Experiment:  I purchased glass bottles of Mexican Coke and put them in the fridge to chill.  To isolate the variable (sugar/corn syrup) as much as possible, I also purchased glass bottles of US Coke and put them in the fridge to chill.  When the bottles were chilled enough, I asked my wife to pour three shot glasses of Coke: 2 of them with one type, and 1 of them with the other type.  It was up to her what to pour in what, as long as both flavors are in there at least once.  She hid the bottles from me.  I drank each shot glass and drank water between each glass.

Results: The first glass was really good.  The second glass seemed…wrong.  Not terrible, but wrong.  I was excited that I already had a result!  The third glass also seemed wrong.  I guessed that the first glass was US Coke and the second two were Mexican.  I was exactly right!

Conclusion:  There is a difference in taste!  Even Coke maintains that there is no taste difference, but that clearly is not the case.  However, as much as I tried to isolate the variables, there are still many differences that I can’t account for: water differences, carbonation amounts, the effect of transport, etc.  If I were in Mexico, I would not hesitate to drink their Coke—it’s very good.  But, given the choice, I’ll stick to good old US Coke.

Clean Code, the end

Well, I've finished Clean Code, but my blogging each chapter is too far behind at this point. However, I thought I would throw out a quick summary blog, and recommend the book one last time before I shelve Clean Code as a blog topic for now.

Clean Code is a book that every developer should read, agree with it or not. It should probably be the textbook for a course in Computer Science (or Computer Programming, whatever) degrees. It teaches a lot of little rules and heuristics for writing clean, maintainable, good code, but ultimately it teaches a process. Care about your code, care about variable names, class names, formatting, small methods, and single responsibility. Your code won't always be perfect; it won't be in the Smithsonian; but it can always be improved, a little bit at a time.

After reading this book, I find myself asking better questions about the code I'm writing. Should this method be here? Should it be named something better? Should it be broken out into smaller methods? Is there any way I can reduce or remove the repetition? While I may not always have the experience and judgment to answer these questions completely and correctly, I think getting in the mindset of always interrogating and improving my code is a good place to be.

I've also been privileged to help organize a great group of developers in Columbus area to form a book club for Clean Code this year. The book provided an excellent starting place and guide for discussions, arguments, and stories about coding. I know that I have learned a great deal more about applying the concepts in Clean Code by just talking to smart, experienced developers. So, not only do I recommend the book, I recommend discussing the book.

The Answer to mobile phone development

I attended the CINNUNG Mobile Development Firestarter event today.  I learned a great deal, as I always do from these kinds of events, and I had a lot of fun.

But as each platform was discussed—first Android, then iPhone, and finally Windows Mobile/Windows Phone—it occurred to me that the most important question is: which platform do I use (assuming you've already answered 'yes' to the question: do I need to write a mobile phone app?).  This is a very important question, because there really isn’t a way to develop the same app (or, at least, the same code) for all three platforms.  Android is Java, iPhone is Objective-C, and Windows is .NET.  So, besides all the technical goodness, this was one of my primary objectives for this Firestarter: which platform do I use?  And I think I have the answer:

Develop for all three.

Wait a second.  Didn’t you just say you couldn’t develop for all three?  Well, yes.  There is no way to build a native app for all three with the same source code.  Ah, you see what I did there?  Native app.  There is one obvious way to build an app for all three platforms with the same code base.  You don't have to go through a costly/obstructive app store either.  It's called the World Wide Web.  You see, I wasn't actually asking the right question.

 

Web apps for mobile have been historically dubious because, well, mobile web browsers have been historically dubious.  But with Safari for iPhone, Windows Phone 7 Internet Explorer, and the Android Web browser, we get three relatively good browsers (at least two of which are built with WebKit) that arguably rival their desktop brethren.  Modern JavaScript can already provide a UI that is responsive enough for many situations, and heck, you can even get stuff like geolocation.

So really, what’s the point of possibly learning a new language, UI framework, API, app store requirements, rules and restrictions, not to mention a possible hefty fee for selling on an app store, when you already have a much more open channel already built in to every platform.  Now, I'm not saying web apps are always the answer (see also: the last 20 years of SAAS vs desktop arguments, not to mention my previous post on RTRJ).  But I do think there's something of an app store “bubble”, and when that dust settles, a similar equilibrium (as on desktops) will be reached on mobile platforms, especially if all these new consumers in the smartphone market have a hard time transferring their purchased apps to their next phone or cell network.