Monday, November 29, 2010

if statement failure.

Looking at an if statement I noticed a problem.   This works, but is technically incorrect.

if( a == null || b==null) {
// do something
} else if( a!=null || b != null) {
// do something else
}

The intention here is really.
if( isSomeState(a,b) ) {
// do something
} else if( !isSomeState(a,b)) {
// do something else
}

which means ultimately it's looking for
(a == null || b==null)
and
!(a == null || b==null)
However !(a == null || b==null) translates into
a != null && b!=null

It happens to work by accident because if either are null the code will go into the if statement and never evaluate the else if portion, however, if the statement were to get more complex intentionally then it could cause all kinds of mistaken errors.

What if the code changed to be

if( a == null || b==null || c==null) {
// do something
} else if( a!=null || b != null) {
// do something else
}

only now the intention is 
if( isSomeState(a,b)  || c==null ) {
// do something
} else if( !isSomeState(a,b)) {
// do something else
}

What was previously be handled by the if statement is no longer handled, and the else if, will handle situations that it did not evaluate before, the something else will happen a lot more than it's supposed to.

When writing complex if statements and the else if is supposed to be the opposite state of the if, then refactor that logic into method and use the method and !method to ensure that the correct logic is used.

Monday, October 04, 2010

How to reliably set the width of an input box.

Input boxes are a pain to get the right length.  There are a few ways you can do it, but only one that is cross browser compatible.

The best way to limit the width is to use the display tag or css.

The css method would be to have a style
.width80 {
 width: 80px;
}


There is a tag that is also supported across browsers, the Size tag this is less reliable.

The size lets the browser know that this text box should big enough to hold 30 characters.   The different browsers interpret this differently.  They have their own internal math that they do and the fonts may be different across browsers, so using the size attribute to define the width of a text box may mean that on one screen the text box is too long and messes with the appearance of the screen that you want to design.

Many times I'm trying to align columns with more of a fixed width, using size to set the width of a text box causes me problems across browsers.  Keep this in mind as you style your own input boxes.

Tuesday, September 28, 2010

IE7 ghost text

This week we ran into an odd problem with Ghost text showing up in our application  Google turned up a lot of similar problems with no clear cause or solution,  I used the development tools to help me figure out a way to solve the problem.  The scenario that it appears to cause it is if there is a div that is floating, it has a width of 100%, and a margin, then the text inside of it may cause ghost text.   Oddly, the same html did not cause the same problem everywhere on the page.


This is setup like this.
PRODUCT DETAILS


Unfortunately, I’m not sure if that is the only thing required to cause this problem.   While I tried to fix the problem it went away with several different things. 
  • When I removed float: left, the ghost text disappeared.
  • When I set margin-left: 0px; the ghost text disappeared.
  • When I changed the structure to the following the ghost text disappeared.
    PRODUCT DETAILS

I went with the last option.  It kept the integrity of the rest of the CSS in place, and made the end result look the way that I wanted it to look.  I’ve seen lots of blog posts about the same problem.  Nobody, including Microsoft, seems to have a clear understanding of what the official cause is.  It only happened in some places in tye application and not in others, even though they were set up the exact same way.   For safety I changed them all to option 3.  IE7 had the problem, but IE8 did not.

A quick note on IE7 vs. IE8,  If you have IE8 installed, you can use the developer tools (F12) to change how the page displays and view it as if it were IE7.  I frequently do this while testing applications because IE7 and IE8 do not show everything the same way, sometimes you have to handle things a little bit differently.

Monday, September 27, 2010

jQuery UI Autocomplete extensions

Scott Gonzalez posted a blog post August 24th about some auto-complete extensions that he wrote.  

One of these is the ability to automatically select the item that is highlighted, so once it’s highlighted the user can hit enter, click it, or just tab off of the field and it will select that item.  There are also some other nice advanced features here, I encourage you to read this post.  http://blog.jqueryui.com/2010/08/extensible-autocomplete/

Saturday, September 25, 2010

jQuery UI 1.8.5 released

jQuery 1.8.5 was release September 17th  http://blog.jqueryui.com/2010/09/jquery-ui-1-8-5/
This is a bug fix release mostly, but it has one powerful new feature that I've been waiting for.  We now have more power over the buttons on the dialog.  We can set them to primary and secondary buttons, as well as disabled.  The styles of these buttons are built into the theme.  There is ui-priority-primary, ui-priority-secondary, and ui-state-disabled.

Also the text on the button is no longer limited to a string, we can now include html, so if we wanted to bold a single word on a multiword button we could have something like “Find account” 

Here’s an example of how to use the new functionality,  
el = $("
").dialog({
                buttons: [
                                {
                                                text: "a button 1",
                                                "class": "ui-priority-primary",
                                                id: "my-button-id-1",
                                                click: function() {
                                                                alert("button 1 clicked");
                                                }
                                },
                                {
                                                text: "a button 2",
                                                "class": "ui-priority-secondary",
                                                id: "my-button-id-2",
                                                click: function() {
                                                                alert("button 2 clicked");
                                                }
                                }
                ]
});

Monday, August 16, 2010

Unit tests catch documentation flaws.

I wanted to set a date and clear the time fields for it.

I quickly grabbed a calender object.

Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DATE, 1);
tomorrow.clear();

The JavaDoc for .clear() states "Clears the values of all the time fields."  Which is awesome because I want the value to be tomorrow's date with no time.

However, the value of tomorrow at this point is 1/1/1970.  The writer of the documentation considered the date as part of the time fields.   

Instead I have to do this.
Calendar tomorrow = Calendar.getInstance();
tomorrow.add(Calendar.DATE, 1);
tomorrow.set(Calendar.HOUR_OF_DAY, 0);
tomorrow.set(Calendar.MINUTE, 0);
tomorrow.set(Calendar.SECOND, 0);
tomorrow.set(Calendar.MILLISECOND, 0);


This will set the value to tomorrow without any time values.

Documentation is great, but be sure to test the results of the function yourself or you may end up with something other than what you expect.

Friday, August 06, 2010

Don't clone an object when you don't need to.

I was working with a piece of code today and I stumbled across a method that had this chunk of code in it.


Iterator iter = results.iterator();
while(iter.hasNext())
{
MyRecords existingTO = (MyRecords)iter.next();
MyRecords newTO = new MyRecords();
newTO.setDateLoaded(existingTO.getDateLoaded());
newTO.setFileExtension(existingTO.getFileExtension());
newTO.setFilenetID(existingTO.getFilenetID());
newTO.setFilenetName(existingTO.getFilenetName());
newTO.setOriginalName(existingTO.getOriginalName());
newTO.setDescription(existingTO.getDescription());

newTO.setFileSize(getFileSize(existingTO.getFilenetName()));
result.add(newTO);
}


This code gets data from a data access layer, then makes a clone of each item adding it to a new list while setting the FileSize.   However, there is no need to create a clone of the object.  The only thing required is to get the file size and set it.   A much cleaner smaller method is.



Iterator iter = results.iterator();
while(iter.hasNext())
{
MyRecords existingTO = (MyRecords)iter.next();
existingTO.setFileSize(getFileSize(existingTO.getFilenetName()));
}


This does the exact same thing without creating all the extra objects to store in memory.

Friday, May 28, 2010

The power of a character.

I was faced with an issue this week.   Code was not working like it should, yet all of my unit tests passed.

The problem, I didn't have a unit test set up correctly.

Here's the scenario.  There are fields in the database that are used for tracking who the last person to update a record is and when that happened.  These fields do not get passed to the front end to prevent someone from using them.

When I save I cannot just insert/update the data from the front end I have to transfer that information into an object that includes the extra fields from the database.

But I only want to deal with that if the record has changed, so I use code that looks like this.

public ViewRecord save(ViewRecord viewRecord) {
  ViewRecord savedRecord = null;
  DBRecord existingRecord = db.getRecord(viewRecord.getId());
  if( recordChanged(viewRecord, existingRecord) ) {
    DBRecord saveRecord = buildRecord(viewRecord, existingRecord);
    DBRecord record = db.saveRecord(saveRecord);
    savedRecord = new ViewRecord(record);
  } else {
    savedRecord = viewRecord;  // did not save, but it didn't need to.
  }
  return savedRecord;
}

Basically every business object in my project does this exact same thing at save time.   The problem I ran into was with recordChanged();

It's code is this
private boolean recordChanged(ViewRecord viewRecord, DBRecord existingRecord) {
  if( existingRecord == null || !viewRecord.equals(new ViewRecord(existingRecord)) ) {
    return true;
  else
    return false;
}

Missing the ! on the equals means that a save will only happen if it is a new record or if nothing has changed.  Effectively turning the object into a write once object.

Code coverage tools may not catch this either.   There is nothing wrong with this code other than it doesn't do what I want.   I even had a unit test that had no changes and made sure that everything was being called to act as if it were saved.  

Unit tests are great, but be sure that you don't use copy and paste when setting them up.   Stop and think about each thing that you want to happen given a scenario, then make sure that you configure the mocks to expect only the calls that you want to have happen.  When you do that, the unit tests will help you catch quirks like a single missing !.

Wednesday, May 26, 2010

Omar Vizquel mulls retirement after season - MLB - SI.com

Omar Vizquel mulls retirement after season - MLB - SI.com

As a Sox fan, I wish he would have mulled over retirment before the season. During the season won't bother me either. Heck the sooner the better. Omar, I hated you when you played for the Indians and beat us in the 90s, but not quite as much as I hate you now that you suck and play for us.

Tuesday, May 25, 2010

Test, Test, Test

Lately my driving force has been more, easier, unit tests.  I want to get my code tested with as little duplicate code as possible and make both my unit tests and actual code easier to read and use.

I will be posting some tips from things that I've been learning soon.

Tuesday, February 23, 2010

Quote

Hope is not enough to deliver a successful project.
-- Manage It