just looking

I’ve been getting a little bit interested in games again. Not interested enough to spend any significant amount of time actually playing a game, but enough to spend some time thinking about them and looking at some interesting stuff.

I still haven’t finished Final Fantasy VIII, which I started playing in 2003. And I’m pretty sure the last time I made any progress with it was 2009. I jumped back in a couple of times recently, but I’m stuck at a boss fight that I can’t seem to get past, most likely because I haven’t played the game in so long I really don’t remember what I’m supposed to be doing. So I did some reading to refresh my memory, including finding a few various FAQs and walkthroughs that I had previously downloaded. So I think I have an idea of where I am now, and what I need to do to progress, but now I’ve kind of lost interest again.

Last night, I spent some time browsing through some of the stuff that’s marked down for Steam’s big sale this weekend. There are some good RPGs on sale cheap, including some good stuff that’s marked down to $1.50 or $3. But I’m pretty sure I’d buy something, then never get around to playing it, like I usually do. So I should really just not buy anything.

Over at GOG, I’ve noticed that they’ve added some more AD&D games since the last time I looked, including Dark Queen of Krynn, which is the one gold box game I never finished. And Neverwinter Nights, which I have a regular boxed copy of, for Mac OS, which I bought and never even installed, plus my brother’s old copy for PC (which he played all the way through, I think).

I’ve also been tempted to try out TIS-100, but I think I’m more interested in the idea than the execution on this one. If I want to learn a new programming language, I’m probably better off learning one that looks good on my resume, rather than one that’s really only useful as part of a game. Jeff Atwood has some interesting things to say about this game, and others like it.

Reading about TIS-100 has made me think more deeply about what I’ve been doing with my spare time lately, and what I want to do with it. I enjoy learning new programming languages, and reading (reasonably) high-brow stuff, but, at the end of a workday, I often don’t have the energy for anything other than TV and comic books. And my eyesight often fades at the end of a day, so doing more programming work is out of the question. Even reading can be a chore, depending on the material and typography. And playing a video game sometimes seems more stress-inducing than stress-relieving.

I wonder how somebody like Shawn Wildermuth can do so much work and travel and still spend 1300+ hours on Fallout 4. Lots of coffee, I guess. I can’t imagine spending that much time on a game, while still being a productive member of society. (Shawn, meanwhile, manages to blog, produce a podcast, create content for Pluralsight, and who knows what else. But I digress.)

I’ve been thinking that maybe learning a bit more about game programming might be a fun thing to do. Daniel Schuller’s book How to Make an RPG looks like it could be a good place to start. If nothing else, I’d learn Lua, since that’s the language he uses in this book. The book is almost 1000 pages long though, so that could be a pretty big commitment. (And I’m not sure if knowing how to write a game in Lua would be any more useful on the resume than knowing how to program the TIS-100.)

To Write Better Code, Read Virginia Woolf

There’s some truth to this article. But you do really need to understand those algorithms too…

I’ve worked in software for years and, time and again, I’ve seen someone apply the arts to solve a problem of systems. The reason for this is simple. As a practice, software development is far more creative than algorithmic.

Source: To Write Better Code, Read Virginia Woolf

F# for C# Developers

I finished reading F# for C# Developers today. I just checked, and I started reading it almost exactly two years ago. (I didn’t really read all the way through to the end today, admittedly; I skimmed some parts that weren’t that interesting to me. But I read most of it.) One part that was of interest was a section on WebSharper, which looks like a pretty nifty way to create web apps in F#. I’d like to play around with that some more.

I also made some more progress on Real-World Functional Programming, reading the chapter on testing, which used xUnit.net for unit testing in F#. I’d never tried xUnit.net before; I’ve previously used NUnit a bit, for C# unit testing, and I’ve also used the unit testing functionality built into recent versions of Visual Studio. So xUnit.net is another thing I’d like to play with some more.

I’m probably going to get side-tracked from this F# stuff again pretty soon, but hopefully I’ll have time this week to make some more progress.

recreational programming with F#

I haven’t done much recreational programming this year. I had some spare time this week though, so I dove back into F#. I picked back up on F# for C# Developers and Real-World Functional Programming, and made a little progress in both. I started reading F# for C# Developers in April 2014, but put it aside when it didn’t seem like I was really understanding it.

In 2014 & 2015, I managed to read all the way through The Book of F#, which was a lot easier to get through and made more sense to me.

I picked up Real-World Functional Programming in December 2015, and made some progress through it in December and January, but then I put it aside and hadn’t had a chance to get back to it until this week.

So my education in F# has been really hit or miss. I’ll mess around with it for a few months, then drop it for a few months, then come back to it. I haven’t been able to use it for a real project at any point, though I’ve used it to solve a few Project Euler problems. (Speaking of which, I see that the last Euler problem I solved was in April 2015, so I haven’t done one of those in a year.)

F# itself seems to be doing well. This Happy F# Day post from Scott Wlaschin links to a lot of the recent developments in F#, including what he calls the “mainstreaming” of F#. So continuing to learn F# doesn’t seem like a waste of time. I should really find a good practical project to use it on though.

Populating fields in SharePoint / InfoPath from query string parameters

As a follow-up to my previous blog post about hosting a web browser control in Dynamics AX, here’s a write-up on how I fudged a SharePoint page / InfoPath form to accept multiple field values from a query string parameter. To reiterate some of the background, the idea here was to be able to open up a new request in SharePoint, from Dynamics AX, with a few fields on the form pre-filled, so that the user wouldn’t have to copy & paste a bunch of stuff from AX into SharePoint.

My idea was to pass those values on the query string, which seemed pretty reasonable. I found some information on doing that with a bit of JavaScript, but that didn’t look like it would work well, for a form that had been created in InfoPath. So then I looked to the “query string URL filter web part”. This web part can be added to a SharePoint page, and allows you to pass a single query string parameter to a field on a SharePoint/InfoPath form. The big issue here is that it only supports a single parameter, so my plan to do something normal, like “?SO=S1234&PO=P1234&item=123456…” wasn’t going to work. After reading this blog post, and some other related posts, I came up with a plan to encode all of the values I needed to pass into a single parameter, of a form like this: “?param=SO:S1234|PO:P1234|IT:123456|…”. Not very pretty, but it would get the job done.

I mapped that one parameter to a hidden field on my InfoPath form, then added a bunch of rules to that field to break down the value and save the parts out to the desired form fields. There aren’t a lot of string-handling functions in InfoPath, but I found that substring-before and substring-after were enough for what I needed to do. A formula like this:

substring-before(substring-after(URL parameters, "PO:"), "|")

can be used to extract the PO # “P1234” given an example like the one in the previous paragraph. This works, but it’s a little tenuous. If I had too much data to cram into the parameter, that would be a problem. Or if I had to worry about having special characters (like the colon or vertical bar characters) in the data fields, then that could confuse things quite a bit. But for my use, it works out pretty well.

I don’t actually do much SharePoint / InfoPath work. Every time I do, I feel like I’ve travelled back in time, to an era when InfoPath seemed like a good idea. (Though I’m not sure it was ever a good idea…) It doesn’t seem to have much of a future, though Microsoft will support InfoPath 2013 until 2023.

Hosting a web browser on a Dynamics AX form

I’m working on an interesting little project at work right now. We use SharePoint to facilitate some workflow around our sales orders and purchase orders. But there’s currently no link between AX and SharePoint, so the sales and purchasing reps have to copy & paste information from AX to SharePoint forms. Not a huge deal, but a bit of a waste of time for everyone. So the idea was to add buttons to various forms in AX that would open a new SharePoint form, with certain fields pre-populated. I might write up some stuff on the SharePoint side of this later, but this post is going to be about the AX side.

The first (obvious) idea was just to launch an URL in the default web browser. And that works fine. Except that everyone is accessing AX through terminal servers. And, while IE is installed on those servers, the internet connection on those servers isn’t filtered the same way it is on end-user machines. So clever users could launch IE from AX, then navigate to restricted sites and possibly infect the terminal servers with malware. Which would be very bad.

My first thought was that there ought to be a way to launch IE on the end-user’s actual PC from the terminal server, but if there’s a way to do that, I can’t figure it out. (And it makes sense that there isn’t, really.) So my next thought was to launch the SharePoint site in a web browser control hosted in an AX form, with no address bar and no way to navigate away from that SharePoint site. Simple enough, right?

After a bit of web searching, I found this article on hosting an instance of System.Windows.Forms.WebBrowser in an AX form. I got pretty far with that, including preventing new windows from opening (which would allow them to break out of the control and into IE), and also preventing them from following links to other sites. But there was one key issue I couldn’t get past: the tab key and control keys wouldn’t work in the control. So the user wouldn’t be able to tab from field to field, or copy & paste information with Ctrl-C and Ctrl-V. I found a few references to this issue on StackOverflow and elsewhere, but no solutions that would have worked easily in Dynamics AX. (They mostly relied on doing things that would work in a real Window Forms app, in C++ or C#, but that I wasn’t going to be able to do in AX.)

So I punted on that, and decided to try just adding the ActiveX web browser control to the form. I’d never actually added an ActiveX control to a form; there’s a good overview about how to do that here. The most important thing I picked up from that is the “ActiveX Explorer” function that can be accessed form the context menu after you add an ActiveX control to a form. That’s how you hook into control events.

I managed to do everything I needed with the control:

  1. Set it to suppress JavaScript errors, via the silent flag. (Our SharePoint site has some messy JavaScript on it, that doesn’t cause any issues, but throws up some errors, if you don’t suppress them.)
  2. Prevent navigation outside the SharePoint site, which I can do by setting a cancel flag in the BeforeNavigate2 event handler.
  3. Prevent opening new windows, which I can do by setting a cancel flag in the NewWindow2 event handler.

And it handles the tab key and control keys normally, without any workarounds.

So that’s about it. ActiveX is a twenty-year-old technology, but it still works. As much as I would have liked to do something fancier, I can’t complain!

Not !Important

I’m currently working on a SharePoint project that’s going to involve a number of fairly kludgy bits, mostly because… SharePoint. I think I may be able to get a few mildly amusing blog posts out of this project. Today’s one is about the !important directive in CSS.

This article titled “When Using !important is The Right Choice” should probably be one word long: never. Understanding specificity in CSS is important, and there are occasions where it’s appropriate to use !important, but only a few. Using it in a site-wide template for a SharePoint site is not one of them, under most circumstances. I had to write a little JavaScript (using jQuery) to hide part of a SharePoint page, and that task was made more difficult than it needed to be due to overuse of !important in the site template.

I’m the first to admit that I don’t know nearly as much about CSS as I should, but I know enough to know when I’m looking at a careful design, and when I’m looking at “let’s just try random stuff until this looks right.” Heck, I probably shouldn’t criticize; the base CSS on a SharePoint site is probably already pretty bad, so someone designing a custom template likely has an uphill battle getting his or her own CSS to work well within the framework provided by Microsoft. SharePoint is old enough that it’s supporting a lot of dead weight from old versions, most of which probably can’t be trashed without breaking too much stuff.

Happy New Year 2016

The last couple of years, I’ve been writing year-in-review/goals posts on New Year’s Day, and I’m going to continue with that this year. For reference, here are links to the 2015 and 2014 posts.

Weight & Health
This category is pretty simple, so I’ll start here. I was at 200 pounds on New Year’s Day in 2014, and 165 on 1/1/2015. Today, I’m at 150. I had set a goal at 160, and got there, then everything past that just happened very gradually. I’ve been between 150 and 155 for the last few months, and I’m comfortable with that. So, for 2016, I’m just going to try and maintain my weight, within that range. Using the Lose It app has become enough of a habit now that it would seem weird not to log all my calories and weigh myself (almost) every day, so I’m going to keep doing that.

On the fitness front, I haven’t made much progress, though I’ve kept up with my habit of doing as much walking as I can. I haven’t started doing any other kind of exercise, and any thoughts I had about that were put aside when I had my hernia surgery a few months ago. I think I’ve healed up enough now that I could consider some new exercise ideas, and I might do something about that in 2016, though I’m not sure what.

My neck and back continue to bother me a bit, and I’m still not sure what, if anything, I’m going to do about it. I will likely buy a new mattress in 2016, which should help, since my current mattress is ten years old.

Speaking of mattresses, I’ve started using Sleep Cycle on my iPhone to track my sleep. I’m still not sure if it’s really that helpful, but it’s at least a little better than my old alarm clock, so I’m going to stick with it in 2016. I used to go to bed around 11pm most nights, but I’ve gotten into the habit of going to bed at 10pm lately. I get up at 6am, so that’s giving me eight hours in bed rather than seven, which is probably a bit healthier. And I’ve started setting my alarm on weekends also, so my time in bed is a bit more consistent now, from day to day. I still have trouble sleeping on some nights, and I’m not sure why. I know that afternoon coffee drinking definitely affects me, but I can have trouble sleeping even when I’m not drinking much coffee. So I’m going to keep thinking about this, and see what else I can do to improve my sleep.

Education / Programming
I didn’t do much in this area this year. I did learn a lot about SharePoint development, for a project at work that never really came to fruition. And I spent some time learning Ruby (and Ruby On Rails). I took Michael Uslan’s Rise of Superheroes course on EdX, but didn’t take any programming courses on EdX or Coursera. And I spent some more time on F#, starting a new book, Real World Functional Programming. I haven’t looked at it in a couple of weeks, but I want to pick it back up this month and get through it. Aside from that, I’m not really sure what I want to do in 2016. My day job is still going to be mostly Dynamics AX work, and I don’t have any consulting work coming up. So I’d like to continue with F#, and Ruby, and maybe more iOS development, but I don’t have any concrete projects that I’m working on or particularly interested in right now. So that’s something to think about.

Work
I’ve been at SHI since January 2013, so I’m just coming up on my three-year anniversary. SHI does performance reviews at year-end, so I just had mine recently, and it went well. I’m reasonably content with my day job, and I’ll likely stick with it through 2016. Since I’m only doing Dynamics AX work there, though, I should really try to get involved in some other projects, outside of work. I didn’t do any of that in 2015.

GTD / organization
I did pretty good on this front in 2015. I’ve kept up on my bills and paperwork, for the most part, and have finally switched over my Merrill statements to paperless. (I blogged about this last month.) I’m got things pretty well-organized in OneDrive now, and I’ve making effective use of my Evernote account. I had started consolidating all my personal notes into Evernote back in November 2014, and I’m pretty happy with the way that’s worked out, enough so that I recently paid for another year of Evernote Premium.

Comics and Books
I donated most of my comic book collection to Superheroes for Hospice early last year, and successfully avoided buying them all back. I have been on a bit of a tear with Comixology and Humble Bundle sales recently, but that’s all digital so none of that stuff is cluttering up the apartment the way 25 long boxes of comics did.

For reading, I’d set myself a goal of 50 books in the Goodreads reading challenge for 2015. I came in at 96, so that’s good, but many of those were comic book TPBs, so it’s not as impressive a number as it could be. In fact, I see that the last prose novel I finished was a Dresden Files paperback, in August. So I should probably start reading a new novel soon, just so I don’t forget how to read the darn things. I’ve done a fair bit of non-fiction reading this year too, long form (but not book-length), mostly New Yorker articles that I read either in the printed magazine or that I’d saved in Instapaper. (I kind of wish that Instapaper had a statistics page I could look at to see what I’ve read recently, but if they do, they’ve hidden it well.) And hey, this article on good news from 2015 looks like one I should save and read!

Life-logging, journaling, and blogging
I’m not sure if I’m using the right terms here, but I’ve definitely been doing more and more of this “quantified self” stuff over the last few years. And also more of the “qualitative” stuff via blogging and journaling. It looks like I wrote a little over 100 posts on this blog in 2015. That’s a pretty respectable number, and some of them took a bit of work and thought to put together. Overall, I think blogging has helped me work through problems, set goals, and keep track of them. (And I occasionally write a post that might actually be useful to someone else, though not as often as I’d like.)

Via my iPhone, I’m now tracking everything I eat, my weight, my sleep, and my daily step count, and I’m actually paying attention to all of those things. I’m not sure how much good it’s doing me, except in the weight loss area, where it has definitely made a huge difference over the last few years. So I’m going to keep doing all that in 2016.

In addition to this blog, I’ve also been keeping a five-year journal for the last nine years. (I’m just starting the last year on the second book.) It’s somewhat useful, but there’s not much room to write anything beyond a few lines, and of course it’s old-fashioned paper, so it’s not searchable. I’ll keep up with it this year, but I’m not sure if I’ll start a new one next year.

I bought Day One for iOS about a year ago, when it was on sale for a buck, but didn’t really start using it. I bought the Mac app last month, when it was on sale for $7, and I want to start using it this year, to supplement the stuff that I post publicly on this blog, and the stuff that I scribble in my five-year journal. If using it becomes a habit, I’ll probably drop the five-year journal in 2017. The guys from The Sweet Setup wrote an ebook on Day One that looks interesting. I may pick that up, and see if it gives me any good ideas.

Hardware and Software
I didn’t do too much with major hardware or software purchases in 2015. I didn’t buy a new desktop or laptop computer. I didn’t buy a new iPhone or iPad. I did buy a $35 Kindle Fire, but that’s a pretty minor purchase. My biggest purchase of the year would be the TiVo Bolt, which is working well for me. I replaced a hard drive cable in my MacBook and the speaker in my iPhone, so I could squeeze a bit more life out of those.

I think there’s a good chance I’ll buy an iPhone 6c in 2016, if such a thing is actually released. My iPhone 5s is working fine, except that the battery is clearly on its last legs, so I’m going to need to replace either the battery or the phone before 2016 is over.

I’m almost definitely going to buy a new desktop computer soon. My current machine was purchased in 2010, so it’s about time for a new one. I’d rather just upgrade some parts in it, but it’s old enough that it’s not going to be able to run Windows 10 without replacing the motherboard, and I don’t want to do that. (And I’m not even sure if I can, and don’t want to waste a lot of time trying to figure that out.)

For software, I’m going to keep up my Office 365 subscription. Even though I’m not doing much with Office itself, the subscription is worth it for the OneDrive space. And I’ll keep using a lot of the applications I’ve been using, like Evernote and 1Password.

Summary
Well, this has turned into a long post, much like last year’s one. I started writing this around 10am, and it’s now 11:45, so I should really wrap this up and start thinking about lunch. It’s nice to have nothing important to do on New Year’s Day. It’s been quiet outside on Main Street all morning, and pretty quiet here in my apartment building. I’d like to go out for a walk, but it’s a bit cold out there today. Maybe after lunch it’ll be warm enough for a quick walk around the block.

Visual Studio 2013 update 5

After upgrading my laptop to Windows 10, I thought about maybe taking a shot at installing Visual Studio 2015. I may do that eventually, but I don’t have any reason to do it right away. But last night, I decided to at least apply the latest update to VS 2013, which is update 5. I’ve had some bad luck with Visual Studio updates in the past (going back to VS 2005 and 2008), but recent updates have been pretty smooth. Well, I don’t know what went wrong with this one, but I started installing it last night, and it’s still going this morning. It seemed to hang at about the halfway point. Rather than cancel it, I decided to just let it keep running overnight.

When I woke up this morning, it had made a lot of progress. Right now, it’s at the step that says “Configuring your system. This might take a while.” So it’s pretty close to the end, I think. I guess I’ll let it keep going while I’m at work, then see if it’s done when I get home. So this could well be a full 24-hour update install. I understand that updating a complex product like Visual Studio isn’t easy, but really, there has to be a better way to do it.

fun with credit card expiration dates

I’m doing some work on credit card processing right now. This is all related to my company’s upgrade from Dynamics AX 2012 RTM to 2012 R3. There were major changes to the credit card processing code in R2, and we’ve customized the code from RTM quite a bit, so there’s a lot to do. I’d like to write more about it, but it probably wouldn’t be of any general interest, plus I don’t want to get into any company-specific stuff.

But one very minor thing came up yesterday that was a little bit interesting. I noticed a support ticket from a user who was entering a new card, and wanted to enter an expiration date that wasn’t shown in the drop-down. (It was too far in the future.) This didn’t have anything to do with the upgrade, per se, but it made me curious enough to look at the code in RTM and in R3, to see what was being done. I was curious if maybe we had something in there like this example from The Daily WTF, or something where the upper-limit on the year was hard-coded to a specific year.

Well, it’s not quite that bad, but it is a bit questionable. In RTM, there’s a drop-down that is populated with years from (current year) to (current year + 7). In R3, it’s pretty similar, except that, when editing the expiration date after initial entry, you can go to current year + 8. (That’s probably an off-by-one error, rather than an intentional extension of the range.)

This all made me wonder what a reasonable upper-bound for expiration year would be, which lead me to this Stack Overflow question, which seems to indicate that there’s no agreed-upon maximum, but that it’s probably safe to go with 15-20 years. So Dynamics AX could stand to be be a bit more flexible on that range.

The other thing that bothers me about the way AX handles expiration dates is that (in 2012 RTM) they’re stored in the database as “MMYY”, which makes it difficult to sort and filter out expired cards. I was hoping that would be corrected in R3, but they’ve only changed it to “MM/YYYY” (without any leading zeroes on the month), which has the advantage of being more easily-readable by a human, and also of storing the full 4-digit year, but the disadvantage of being even more difficult to sort on, since the year sometimes starts in the 3rd position and sometimes in the 4th.

And let me end this blog post with a link to my very favorite publicly-documented method in AX, related to credit card processing: CreditCardWizard.codeCoverageFudge. I’m not entirely sure why this method exists in the released product, but I’m guessing it was added to fudge the code coverage numbers in some unit testing metrics. Maybe a certain percentage of code coverage had to be achieved, but there was no easy way to write meaningful tests for the remaining uncovered code, so they just wrote a method that does nothing, and a unit test for it?