Iterations in software development. Tried to implement proper solution on the first try? I bet you failed. It’s like in Google Earth zooming in your house from the planet view. To achieve your goal, you’ve got to advance a little bit, adjust your position, advance further. Iterate until done.
Making More Mockups
Today Elen, my manager, approached me and asked to make a prototype of a new functionality in our project management system. This is a reimbursement management module: employees spend some money (taxi from airport, for example), then they create requests for reimbursements and if they are lucky and management approves the requests, they get the money back :-)
So, prototype it is. I fired up my Balsamiq for Desktop and in under ten minutes mockups of two pages were ready. This is one of them:
But when I sent them to Elen, I thought that maybe she meant some real code, or HTML stubs in real system, because there was a mockup attached to her original email. Here it is:
According to her, she made it in Paint (duh!). And it took her approximately 30 minutes to make this one, because she had to printscreen some real pages and cut pieces from them. What a tedious work! :-) And it must be a hell to modify such mockup!
When I told her about Balsamiq Mockups, she became very interested and decided to give it a try. Another happy story. Thank you, Peldi :-)
Related posts: Creating UI mockups with Balsamiq
SugarCRM: More Colors!
When I was implementing previous issue, my manager asked me: “Can we also mark meetings with colors, corresponding to users?”. This way it becomes somewhat easier to identify originator of an event. “Yeah, it would be cool, but it can be tricky and difficult to implement”, I said, rejecting the feature request. I said so just to save my ass from potentially frustrating project. Just the day before Marcelo had told me that he has a friend who was working with SugarCRM for a year and he hadn’t quite enjoyed the experience.
But later at home I was thinking about it and decided that it may not be as hard as it looks. We can divide the task into two subtasks:
- provide a unique color for each user
- use this color when generating markup for an event
The latter subtask was quite easy to implement, I already knew a place where the markup was generated. I was more scared by the former one. If done in “enterprisey” way, it could involve new property in User entity, new configuration screens, database alterations, etc. But there is a solution almost as good as abovementioned and much more simple. Let’s define a function that maps user name to color. md5() is a good candidate :-)
1 2 3 4 5 |
|
I also used RGB<=>HSV transformation functions, because I wanted to get lighter colors. Initially I wanted to highlight event’s name with the color, but it turned out that text is not always readable. I decided not to write functions that calculate good contrasting colors and put a small color rectangle instead of highlight. This rectangle is essentially a span with several ‘s as a body.
So, final result looks like this:
Here is complete patch (it has too big lines to look good on this page)
Unmount This Drive… Please?
One thing I dislike in my current Vista installation is how it behaves while trying to unmount USB harddrive. I have a 320 gig external drive, which serves as a storage for my backups, torrents and videos. Also I store and run different virtual machines from it.
This morning I was about to go to the office. I shut down uTorrent and clicked “Safely remove” on my drive. “This disk cannot be removed right now. I don’t know who uses it, but someone surely is.” was the response. I tried again. The same result. Hmm, maybe some program or explorer window is indeed hanging around. I double-checked all icons on a taskbar, then running processes in Task Manager. Nothing.
“What’s wrong with you?”, I said to the laptop and tried once again. “Now you can safely remove the hardware”. Oh, thank you so much! Why couldn’t you do it the first time I asked you? (And this happens to me on a regular basis, daily. Sometimes, two or three times a day).
As a tech guy I can guess what’s happening. uTorrent opens a lot of files and it probably takes some time to close them and flush all buffers to the drive (which is not very fast, it is external tiny box). Ok, no problem with that. But couldn’t it be done synchronously? I think, Windows can easily recognize situations when some program has open file handles on the drive, or just some file buffers need to be flushed. In the latter case it could show a popup “Removing the drive, please wait…” and do its work. That would leave no space for speculations.
In the other case (when a program uses a disk): is it too difficult to point at the culprit? Some installers can do this. And I am pretty sure there is a 3rd party software that does this. This is pure usability issue. I hope they’ll take care of it in Windows 7.
Formatting With Named Parameters
Problems with formatting
The “official” way to format strings in .NET BCL is to use String.Format method (and wrappers for it, like Console.Write).
This is not very reliable method. You can forget to include parameter into the format string or confuse one parameter with another. And your IDE does not offer any help here.
We want better way!
People feel that this is not right and try to invent some more convenient methods. One of which is formatting with named parameters (using names instead of ordinals). Yesterday I read this blog post. There are several implementations of formatting with named parameters and author makes more reliable and efficient implementation just for fun. But you know what? It still doesn’t seem right.
Anonymous type here is supposed to protect us from renaming issue, but it clutters the code. And again, we do not get any help from IDE (warnings about non-existing elements, highlighting, etc).
But how can it be done even better?
Let’s look at Nemerle. It borrows “spliced string” syntax from languages like PHP (“hello, $username”). But it has several advantages over PHP and Perl. All expressions are resolved and typed at compile-time. And if you use VS package, then you’ll get development-time checks (on-the-fly) and highlighting.
One picture is worth a thousand words. So look at these code samples
Feel the difference! What can possibly go wrong here (except for NullReferenceException, but string.Format is also vulnerable to it). Also, this code is very efficient. Essentially it is transformed to a series of string.Concat or StringBuilder.Append calls.
P.S.: One more thousand-words-picture.
Case Sensitivity and Tools
I want to say again that decision to make identifiers case-insensitive is one of the worst design decisions a language author can make. Along with that goes “declare on first usage” decision, but more on this later.
Why is it bad? Because you either have to have proper development tools that support this decision, or assume high professionalism of the developers, letting them use conventional tools. Good professional developer will be consistent with casing of identifiers, because he sticks to some naming convention and case means something there (this is wild assumption, but I believe it is true, hehe).
Recently I had to fix some ancient program. It is written in Turbo Pascal 5. The IDE is even more useless than even Windows Notepad (can you imagine this?), that’s why I used Notepad++ to edit sources and launch compilation script.
In some recent versions it acquired so-called “smart highting”. This feature highlights all occurrences of a word when you select one of them. Very handy. BUT! it is case sensitive.
Take a look at the screenshot. You can see two occurrences of valor highlighted with green color, but another occurrence is not highlighted, it has different casing. This makes analysis of this source code somewhat harder.
Well, we could blame two sides here: lack of “case sensitivity” options for Notepad++ and this design decision of Niklaus Wirth. I tend to do the latter :-)
Creating UI Mockups With Balsamiq
Virtually in every project you have to do some UI mockups. I mean, if you have some methodology, you are a team and you are serious about your project.
In my past experience I have tried different ways of creating mockups:
- hand-drawn pictures;
- hand-drawn pictures, photographed with digital camera and inserted into requirement doc;
- Visio documents (duh!);
- some actual code.
While the last way serves some extra purposes (other than creating mockup itself), it takes a lot of time. And sometime you just need to share with others a picture you have in your head. Ways #1 and #2 serve very well, but have one major disadvantage: if you want to modify a picture, you have to redraw it from scratch (or make a mess from the original one). And yeah, Visio way does more harm than good: it takes enormous time to create a picture and then you often “forget” to update a mockup, because you don’t want to launch that app again.
So, what options do we have?
Recently I discovered an excellent piece of software, called Balsamiq Mockups. It is simple, effective and nice looking. It requires zero learning time. For example, I tried to create something for my personal project, yet another photo gallery. And I got this mockup ready in exactly 6 minutes after I started the demo:
Impressions: product - great, support - fast and fully satisfying, overall - have to get one.
Also I want to quote Charles William Stanton here:
Before, I was doing far too little GUI “prototyping” because either the results weren’t reusable or the effort took too long; now I fear I may be doing too much because it’s just that much fun.
Go to the product web site and see it for yourself.
Entity Framework, SQLExpress and Remote Connections
Today I had to fight one small, but highly annoying problem. It is related to Entity Framework and SQL Server connection string. When you create a .edmx file with your model, the wizard automatically inserts proper connection string to your app.config or web.config file. Well, it is not always correct string.
In my case, I have .edmx file in a class library and it worked fine when I was using it from WinForms application. But then I decided to put it on a web site. And it ceased to work. The only thing I could get from it was
SQL Server 2005 SQLExpress error: …provider: Named Pipes Provider, error 40 - Could not open connection to SQL Server
I tried many things, but in the end it turned to be some mistreatment of a connection string. Mine looks this way:
The problem goes away when I put a backslash instead of slash in “./SQLEXPRESS”. It looks pretty weird, because they always used forward slash in such autogenerated connection strings, didn’t they?
P.S.: Sorry about connection string being image here. :-)
Silverlight: Security Error
Sometimes, you may get not-very-descriptive System.Security.SecurityException. Stack trace tells you that something bad happened somewhere inside EndGetResponse, and that’s it, no more details. One possible cause is this: in a Silverlight project you may tell it to generate a temporary page that will host your application.
And if your application sends requests to some host (a linux virtual box, in my case), this will be the source of pain. The dynamically generated page gets loaded to Internet Explorer as file://your_path/TestPage.html. And you are trying to reach HTTP(S) host. This cross-scheme behavior is not allowed.
For more information, see this MSDN article.aspx) and this forum thread.
Silverlight 2: Trouble With POST Requests
I am trying to make a small Silverlight control that talks to PHP server. Sometimes problems arise and I have to deal with them myself, since there’s not much information on this topic in the internet. Trouble of the day is:
The remote server returned an error: NotFound
when trying to make simple POST request to a PHP page. I’ve spent half a day diagnosing this problem. And solution was found entirely by chance, because exception messages weren’t helping in any way. I mean, I was always getting abovementioned error message, without any details (what host, what page, request parameters, etc). But enough of complaints, let’s proceed to the solution. The troublesome code was this one:
1 2 3 4 |
|
SessionID was null at the moment and this made HttpWebRequest so pissed off that it even wouldn’t send request header to the server ! And because of this, Fiddler was completely useless here. After adding necessary check, everything started working like a charm.