Thursday, August 30, 2012

Common programmer interaction mistakes

Having worked at a number of companies I see the same programmer interaction mistakes made over and over. Maybe if they are brought into the light they can be avoided at your company.

Thinking something is too hard to code

QA, a client, support or any other person who uses the software runs into an issue. They feel like it would be impossible to implement so they never ask. So many times it turns out it is far from impossible and a lot of times it is under 50 lines of code.

Many times you will hear about missing functionality accidentally. Maybe you overhear a hallway conversation or someone in a cube close to you says "I hate this area, why does this button not have a hot-key?" There are a lot of questions that never get asked of the correct person.

The job of our medical coding team is to enter a lot of data for medical insurance claims. I had the chance to sit down and ask them what they wanted to change in the software. One of the big issues was entering decimal places for ICD-9 codes. They said software they used at other companies did not require them to enter the decimal point. Made sense to me so I changed the code to not require the decimal point but to also work if you typed it. This way the data entry did not appear to change to those who are accustomed to typing the decimal place but allowed those who did not want to type it the freedom to avoid it.

I told the project manager I was able to implement this feature and they went off on me. Before I even got to explain how it worked they told me I was breaking the software for everyone else. They had been telling people "No" for years on this request. I screwed it all up. Once they got done with their rant I explained how it worked then the calmed down and said everyone would love it. I went through the same scenario with QA and other staff members, tell them, rant, explain, smiles. It was so ingrained in their minds that this was impossible to do without destroying existing users that we could not do it. There have been many requests for this feature at our user group meetings and via the support ticket system. Of course I did not know about that, I was just told by a user how much easier it would be for them so I implemented it.

Not informing you of repetitive tasks

Copy / paste is available in some areas of the program but not others. Ask if it can be implemented everywhere. If you do a lot of copy / paste maybe you need the program to auto-fill values or if you are doing the paste into another program where you find yourself reformatting or deleting a lot of the pasted data find out if export functionality can be added. 

If it is repetitive and boring then the computer should be doing it for you. Nearly every time I have been asked to do someone else's job while they are on vacation I have found ways to automate the process. In one case a guy I worked with manipulated a Lotus 123 spreadsheet everyday. He was on paternity leave when his son was born. I was a programmer but I was asked to deal with his work too. For some reason I did not find an extra 8 hours in each day he was gone for me to do his job but I did automate it with some Clipper code to run in about 10 minutes time. He came back and found a new job within the company. Did not want you to think I am proposing the use of robots to take over the jobs of new fathers.

Not asking for a feature because only a few need it and they don't want to affect everyone.

The wonderful thing about computers is the availability of settings. Of course we don't all like the same defaults, color schemes, keyboard mappings etc. That is why programs have options screens to configure it to your liking. You need a large font, here you go. Hate the color red, use blue instead.

The other great things about computers is they take care of the boring stuff. Have an Excel spreadsheet you do the same to every day? Automate it using macros! Have a spreadsheet you need to export in CSV format once a week to import into your software? Find out if there is import directly from XLS instead. We do this using Apache POI for our Java code.

Thinking something is easy to code when it has huge system impact

Hopefully this is discovered during sprint planing. At times what seems a tiny feature can impact nearly every table and index in the database. Yes this is the opposite of my first point. Why there is so little middle ground between what a user thinks it will take to do something and what a programmer knows it will take is a big life mystery.

The area to watch out for is always saying "No" to big impact items. If you are doing a 2 month release cycle and something requires 5 months and it will really help the clients then you need to break it into smaller pieces or split a person off with development time to complete the project. You can't just ignore everything that does not fit into a neat little schedule. If you do your program will grow with little incremental fixes but will not GROW with new functionality. Other companies will come along with the missing pieces and take your business away.

Please ask, all the developer can say is "No"

First off your end users, QA staff or anyone who uses the software should never be afraid to ask for a feature. Yes, it might have to make it through the proper channels to be assigned to a release but really the worst that can happen is you are given "No" as the answer. I have seen some many really useful features blocked by the wrong people. People who assume it is impossible or it will break how existing users operate. Unasked questions are rarely answered.

It could be the full solution can not happen right away but it can be partially implemented along with another feature. This happens a lot. If I know a feature is coming in the future I can plan they way I am coding an feature now to accommodate what you need in the future. You never know, it might just come along for free due to some other code I was refactoring. For some reason places find it better to hide all future work from the programmers. Not sure why everything being a big surprise makes them think things will go smoother. I can handle knowing that a feature is for two releases out. If I know it is coming I can make sure any code I am writing now is flexible enough to handle the requests later in the pipeline.

How programmers can help

As a programmer it is our job to do our best not to break existing code. At times we have to write migration routines. We may have to allow the program to run both the old and new way. Settings will be added with the default to the way it has always been. Of course there are times with the old does not mesh with the new. Clients will complain, probably for a few weeks, then they will get used to the new more powerful way. Change just to change is not good, change with clear benefits will pay off.

Don't be dismissive with your end users. Sure, they are going to ask for really weird things that make no sense. Some of it will seem so easy to them they don't understand why you tell them it will take 10 months to code due to current code or database layout. Don't roll your eyes and them and get all technical on why it will be a bear to write. Explain that your initial thoughts point to this being a rather involved process. If they press for why you feel that way give them enough technical details so they can start to understand the complexities.

There are times you are going to mentally block a real solution and even you will think something is a 15 hour project. Later at home when you mind is a bit clearer because you are blasting pixels in a FPS you will hit a 12 minute solution. That can't happen if you did not know the problem even existed. Be open to suggestions always.

Try to find the time to sit and watch the people who actually use your software. It can be in house users or an actual client site visit. They don't always know that they are doing it the hard way. They might not realize there is a hot-key or a "Yes to All" option or another entry screen with just the data they need. Maybe they have never used the export or import functionality. 

It really is not us against them. It is us and them getting the computer to make our lives easier. The computer has no feelings so always make it the "bad guy". Take all the suggestions: good, bad, ugly, freaking weird and keep a physical and mental list of them. Over time you will knock them off here and there making everyone happy. I keep a tabbed text editor open always. I have a tab for each project, one for general notes and one for each platform I work on open always. I end up adding and deleting from my to do list all the time. When people stop by my cube to talk to me I add notes as needed. Too easy to forget little ah-ha moments and I don't want to miss out on anything that will make the software better.

Don't be afraid to fail. There are times I pull a task off the wish list, work on it for a few hours and stop saying to myself "well, I guess I don't have a solution to that". No harm, no foul. Maybe later I will come up with a solution based on my failures. Other times I look at something I typed in a number of months back and a quick solutions hits me, I try it and have success in 15 minutes of coding. That is one of the best coding feelings you will ever have. 

Sometimes I am asking Google about a current issue and part of a post will have a new direction to take on a seemingly unrelated issue. I might cut and paste that into my notes or I might have the time to tackle it right away. I have a lot of code snippets laying about that I have not used yet but am pretty sure I can use in the future.

Monday, August 27, 2012

Experimenting with HTML5 Canvas and JavaScript

I keep hearing about HTML5 especially in the mobile realm so this weekend I decided to see what I could make the canvas do using JavaScript. I have already written the new schedule viewer in Objective C on iOS, Java on Android and Java on the desktop so what the heck.

First attempt was grabbing some sample code of the web and tweaking it until I understood the basics of HTML interaction with JavaScript and basic paint commands for the canvas. I was doing this all via Eclipse and Chrome. I tried to get all the proper plug-ins installed for Eclipse but was not having much luck. I found WebStorm from IntelliJ  and installed that then things became much easier. I could actually put in break points and debug my code. If the code flat out did not run then the basic inspector in Chrome gave me the information I needed to track down those issues.

Again it has been very handy having a multiple monitor setup at home. I can have plenty of space to run WebStorm, NotePad++ etc. on main monitor and Chrome on the second screen where I can test the running application. My second monitor was a free, not super high resolution but still darn handy. Get one if you don't already have one, they are a programming life saver.

Currently I have the following working on the canvas:
Paint time margin (with various gradients)
Paint column headers
Paint grid lines
Paint dead areas outside of grid
Hold down middle mouse button and scroll around in grid

Various "objects" are set up, same objects as in the other implementations. I learned how to get the canvas to resize to fill the screen as you resize the browser. Mouse interactions including up, down, move and exit are in place. I am sure I am still doing various things incorrectly or the hard way but the code appears to be pretty clean and the paint codes runs nice and fast.

JavaScript is very close to Java for general syntax making it pretty easy to adjust to coding in it. You don't have strict variable type checking, arrays and maps have a different syntax but are really easy to use, variable scope is a bit lacking as are name spaces. Most of the code conversion was very straightforward. I can really see where it would be very handy to have a single code base for all platforms from mobile to desktop to OS of choice. Straight Java covers the OS of choice side but does not handle mobile. 

I don't see any painting limitations and the canvas 2D API is feature rich and very fast at painting. I need to chuck the code over on my server and see how it runs on the tablet when I get a little farther along. I also need to tie in the touch events to match the mouse events which should be very easy to do.

Where is will get interesting is in all the user interactions. On the PC you have click, double click, left / right / middle button processing potentials. On a touch device you have tap, double tap and long press. There are times you have to get really creative to handle user interactions. Normally on a touch device a long press will bring up a menu and double tap does a default action (which should also appear in the menu). On a PC a right click shows the menu and double left click is default action.

Still more to learn on the HTML5 / JavaScript side but I am very happy with how much I was able to get done in a few hours this weekend. The web is full of helpful examples and I have dealt with enough programming languages, SDKs and 2D APIs that I was quickly able to get it painting what I wanted.

Tuesday, August 21, 2012

You can't do that!

My job this week was to sit in with our medical coders to find out how we could make their life easier. One of the items mentioned by many of them was the requirement to type in the full ICD-9 code including the decimal point. Other software does not require this as the decimal point always occurs at position 3 according to them. If other software does it then it must not be too hard right?

If fact our FoxPro based product does not require you to type the decimal place. As we convert people from that product to the new Java / Cloud based product this has been a sticking point with them and for good reason. Your data entry staff wants to type the least number of keys possible.

Being a non-tainted innocent comes in handy when programming. I had no background on this issue. I implemented and tested the code in a hour or so. We are using a JIDE shrinkable / searchable combobox table to handle the data entry for this field. As you type the visible content of the table shrinks until it becomes the one matching code. I updated the shrinkable and searchable code to handle everything with and without the decimal point. I also found E codes have the decimal point at the 4th position instead of the 3rd and S codes don't have a decimal point at all. Code a couple of IF statements and those rules work as well. Put in a boolean so you only set this special processing when you are on a diagnosis field and I am done.

I begin to tell people I fixed the issues and they start to have fits! You are going to break all the old clients! I have told everyone you can't have that! The decimal point is right on the numeric keypad, they can type it! Whoa there, I did not break anything. You can still type the decimal point like before, if you skip typing it I do the search with it in the proper place. I handle the edge cases.

People were saying NO NO NO because they only saw one side of the solution. They hit the "it will break others" point and stopped. I had no intention of breaking existing user's data entry habits, never ever considered that a viable option. When programmers are not involved in decisions then this sort of thing will happen. They don't ask the programmer because they have already determined it is too hard or impossible. They will then turn around and require you do something that is nearly impossible that they feel is super easy. Your company needs to have a good feature request vetting process in place. It never hurts to ask but is sure can hurt to not ask.

Everyone has calmed down at this point. They really are happy this feature is in place. Our medical coders are going to be really happy when the new release comes their way in a few weeks. QA will have to get it a solid beating before it is released but the testing is pretty straight forward.

I am ready to move on to the next seemingly impossible issue.

Thursday, August 9, 2012

iPad development to influence my PC code

I am converting the Java WebStart JIDE CellSpanTable based appointment scheduler to the iPad. It has a slightly different purpose on the iPad but needs to display the appointments in almost an identical way. The Java desktop application was recently converted from MigCalendar to JIDE CellSpanTable by me. I was pretty happy with the results but now I am thinking of refactoring it again.

Why bother? First there are some limitations to the CellSpanTable. I am using a JXLayer to get around some of them. That allows me to paint on top of the grid to show the current time line and for Drag and Drop support. Things are a little screwy when I attempt to scroll to a starting position in the grid. When I do that some of the paint offsets are incorrect. I have made all the adjustments in the code to handle this conflict between the JScrollPane and the CellSpanTable.

I also have issues with the time margin not fully painting in sync as you scroll the grid vertically. When you stop dragging the scroll bar everything lines up, just during the drag there is a stutter. This sort to thing always bothers me.

Since I am spanning cells based on appointment durations I can only pick one background color for the full cell span. This means if the appointment starts before normal business hours the spanned cells all get the "business is closed" background color which is not accurate. I also don't get the grid lines painting across any cell that has a spanning appointment.

I have to track extra information for cell spanning and the code is a bit difficult to grasp every time I look at it. I hate code like that. It is complex because it is not an easy process but it is hard to explain why I did what I did to make it work.

When I converted the code to the iPad I did not have a 3rd party grid control to help me out. The nice thing is I was able to concentrate on doing my own grid because I already knew how to do all the other appointment painting, time margin painting etc. I knew all the limitations of the JIDE grid that annoyed me. I was not overwhelmed with the full rewrite of something that I did not fully understand so I could initially concentrate on the grid. In fact I was forced to concentrate on how to get a grid to paint, there was no easy way out. I did some searches on the web just to make sure someone did not have a workable solution but I did not find anything to fit my needs.

I have written many a custom control so I was not afraid to tackle another one. I was able to use Quartz on the iPad to manually paint the grid and all the appointments. I solved numerous issues I had with the JIDE grid while coding the new control. I am fully in control of all the painting. I don't have any scrolling sync issues. I don't have to use an overlay painter - I paint things in the Z order I need. I am not using a grid data storage system that does not completely apply to what I am attempting to do. There are no scrolling coordinate offset issues.

This is not a generic cell spanning grid control for the iPad. This is a highly optimized grid for the purpose of painting an appointment schedule. Not that I couldn't take some time to make it more generic. My goal was to get something running that was super optimized for my painting needs. I want a very responsive UI for this application. I also will convert this to the Android platform in the near future. It should be a fairly straight forward port.

Based on the painting I did on the iPad I have already improved the look of the PC Java code. Taking a second look at things and being under less time pressure I was able to come up with a nicer look to the appointments with the start / end time in a darker color to visually highlight them to the user. I also drew a pointing ball in the margin to visually enforce the location of the current time line that can get a bit lost in the grid especially the current time falls on the hour. Just adds to the professional feel of the app.

I don't have the issue with grid lines not painting as I paint them first then overlay the appointments. The proper background color is painted for the cells too since that happens independent of the appointment paint.

The appointment memory storage is much cleaner because I am not taking what I need and forcing it into the memory layout of the grid so it can ask me to paint the appointments as it is painting each cell. Using Quartz I just paint my layers - verifying that what I am painting is visible on the screen based on paint offset and component size - avoiding all sorts of callbacks and other overhead.

On the PC your scroll with the scroll bars but on the iPad you scroll via touch. I really like the way touch scrolling works on the iPad and I miss it every time I run the PC app. I keep trying to click drag the PC app just like I do on the iPad simulator. Maybe I will have to implement that on the PC too!

Other than the auto-scrolling of the grid as you drag and drop an appointment I think the conversion will be pretty easy. The JIDE CellSpanGrid did the auto-scrolling for me. Not like this is some super secret magic bit of code, just need to write it up and make sure it feels right when it is done.

I am looking forward to tackling this on the PC then again on for Android devices. I am sure I will optimize it just a bit more on each one. The first time you write code it always stinks, you have too big of a picture in your head. On the rewrite you can concentrate on the minutia. You are basically doing a code review of your own work as you convert your logic to each language / platform.

There was a lot of learning around Quartz during this project. Sure I will learn more about Graphics2D under Java too. I have used it enough to have a pretty solid grasp there but something new pop-ups with each project.

Friday, August 3, 2012

Thanks Apple, nice general settings on iPad simulator

For my iPad scheduler app I want to follow the overall settings for 24 hour time. Guess what? You can't set that on the simulator! Under Settings -> General they flat out skipped the Date & TIme options. Why? There is no reason to not have this setting available. I have to do all my testing of time and date formatting on the device itself.

I am trying to be as friendly a developer as possible. If you like 24 hour format then times should appear that way in all your apps. I am used to AM / PM so I generally use that format but Kevin != rest of world.

At least I am not doing a ton of time and date formatting meaning it was pretty easy to test on the device but I should not need to switch to that to test an OS related feature.

An interesting side project that ended up in main project

We are getting PDF files from a client. They contain medical records with one of the items being the patient ID. My initial task was to find PDF parsing code on the web to pull the patient ID from the file then rename the file to include that as a prefix.

A quick search turned up PDF Box from Apache http://pdfbox.apache.org/ which sounded like it would do what I needed. Grab the download, whip up a simple Eclipse project and I have the text extracted. Very easy to use and understand API.

Of course the next part is where the real work comes in. Have the program respond to command line parameters and if none are provided a GUI is presented to the user. Let them pick the source and destination directories then process the files. Save the last used directories to an INI type file so they don't have to pick the directories every time they start the program.

Once that was working I was told they would really love to have the PDF pages converted to a JPG so they could be imported into our software. Turns out PDFBox can convert to PNG which we can also import. Update the code to handle the conversion. They also wanted to copy the originals of properly converted files to an archive directory. Added that to command line processing and GUI.

I asked since I know now how to use the library to convert PDF to PNG why don't we just import PDF files directly? Sure, why not, do that. I updated the main code base to allow user to choose PDF files along with other image formats. Next I changed the processing loop to handle the page count of each PDF for the import status and did all the code to write the converted pages to the temp directory and then import them as PNG files. All pretty easy stuff and it turns out this is something the clients have asked for over the years.

Before we did not want to import straight PDF files as then we would need a PDF viewer in the code. Adobe used to be pretty good for a C/C++ developer allowing you to embed the viewer using OLE and other API calls but that came to a halt I think around version 9. It has never been a fun task in Java. With the conversion to a normal image format I don't have to worry about any of that. Each page can be rotated, annotated, redacted, etc. using our basic image tools.

Now I asked about the original utility program I wrote. Seems pointless for it to convert the PDF to *page#.png files now that we can import things. This morning I am going to add a checkbox to the GUI and another command line parameter to allow you to control the export of page files which will be off by default. They still need the patient ID extract and rename but probably will not use the page extract. With the code already written it might as well stay in as an option.

Funny how a one off request can turn into something that benefits every customer. There are days you just need to do a little research to find really cool simple solutions to problems. I also got to learn about a new library that may come in handy for other projects. The JAR file is not small but what it does is pretty powerful. We added it as a lazy load JAR to our JNLP file. Hopefully QA does not find any massive issues with the conversion. It worked fine on all the PDF files I tried it on but I know there are a lot of ways for those to be messed up.

Wednesday, August 1, 2012

Jelly Bean on my Xoom

Jelly Bean arrived on my Xoom last night and so far I like it. There are new animations during app transitions, when you have multiple unread emails you get to see the subject of each of them in the notification window and everything seems to be snappier which was the main point of this release.

Install was a ~80meg download followed by the install and reboot. Of course once the machine reboots all can seem snappy for a bit until you run a bunch of apps. I will see how this version does over time. It does look like Google is taking the knocks against Android seriously though. Always tough to fix something without breaking something else. All the apps I tried last night worked like a champ.

I think some of the new transitions happen during certain initialization stages of the app. I watched the USA Today app run a couple of the new transitions more than once which probably means that app is doing something odd that needs to be adjusted. As a programmer I know I have run into this in the past. You don't realize you are doing some initialization twice until you see the screen flicker, a double message in the log file etc.

Curious if they will come out with a version of Jelly Bean for my phone. Might be the thing that pushes me over the edge to root the phone and install something no directly from Samsung. Since Samsung no longer does OS updates for my phone I don't feel bad about doing this or worried that I will screw it up not waiting for an official release.