May 232013
 
English: communication between object classes

English: communication between object classes (Photo credit: Wikipedia)

Structs tend to be underutilized in .NET, and I think part of that is that developers aren’t quite sure where they fit.  In an effort to make structs easier to use, various iterations of .NET have added a lot of class-like features to structs.  Unfortunately, this tends to obscure the issue even further.  There’s currently almost nothing you can do in a class that you can’t do in a struct and vice-versa, so why would anyone use anything but a regular class?

Discussions about the differences tend to revolve around memory management, and they’re usually incorrect.  They talk about classes being stored on the heap and structs being stored on the stack.  Not only is this not accurate, but it’s also not necessarily helpful information from a design perspective.

Then, people start talking about value versus reference types, which is a much more accurate categorization, but once again is of limited value from a design perspective.

So, here’s my nickel test for whether something should be a class or a struct:

If you take away the unique identifier field, could two instances with completely matching properties still theoretically be two, different things?

This can be kind of a difficult question for some people because many people (sadly) learn application development from a database-first perspective, and if you see two rows that have exactly the same data except for the unique identifier, we’re conditioned to think of that as a duplicate and not two actually different entities.  And, honestly, that’s probably what it is.

That’s why my test has the word “theoretically” in it.

If you have two Persons with the same name and same address, they are probably a duplicate, but theoretically, they could be two, different people who have the same name and live at the same address.  All the values being the same does not guarantee they are actually the same person.  Therefore, a Person is a class.

However, the name “John Wesley Smith” is always the name “John Wesley Smith” no matter how many people share it.  If all the values are the same, they are the same thing.  They could not, theoretically, be two different names with all the same values.  That doesn’t even make any sense.  Two Names that have exactly the same FirstName, MiddleName, and LastName are actually the exact same name.  So Name is a struct, not a class.

Address is (generally) the same way.  If you have two Addresses, and they have the exact same StreetAddress1, StreetAddress2, City, State, and Zip, then they are the exact same address.  They could not theoretically be two, different Addresses with the exact same specifications.  So, Address is a struct.

Two Movies could have the same Title, same Director, and same Cast and still, theoretically, be two different Movies (however unlikely that might be), so Movie is a class.

What we’re really getting at here is how you define identity.  Two different People are always two different people even if everything about them is exactly the same.  Two different Names are actually the same name if everything about them is exactly the same.

This test is just an offhand test; it’s not a rule.  An Address can be a class depending on how you define and use it.  A Name might theoretically be a struct but, once you measure how the memory for it is actually being allocated and its influence on performance, you might switch it to a class to see if it changes anything.  Various mapping and serialization tools might be easier to use with one scheme or another.  So, the little test isn’t the last word in whether or not something is a class or a struct, but from a design perspective, it might help point you in the right direction.

Enhanced by Zemanta
Mar 282013
 

If you use jQuery dialogs and create the buttons in the JavaScript, you need to be aware of a few things:

  1. The button text is inside a span tag within a button tag, so you can’t find the Button object directly by text.  Finding the span and clicking the span work just fine.
  2. The button lives inside a DOM generated div with a class of “ui-dialog-buttonset” and not directly in your dialog div.

So, the quickest and dirtiest way to click the button would be something like:

Browser.Document.Span(Find.ByText("Save")).Click();

But you’ll probably want a selector chain much more specific than that, especially if you have more than one dialog form on the page.

I couldn’t find anywhere on the Internet that spelled this out for me, so I hope this saves somebody somewhere a little time.

Enhanced by Zemanta
Sep 192012
 

I ran into this issue where I had some jQuery JavaScript attach logic to the onChange event of a select element:

$("#role-level-selectlist").change(function () {
    if ($("#role-level-selectlist").val() == "11") {
        $("#role-level-textbox").show();
    }
    else {
        $("#role-level-textbox").hide();
    }
});

 

Testing this using SpecFlow and Watin, I discovered that

_currentPage.RoleLevel.Select("Other");

 

did not fire the onChange event.

However, jQuery can manually fire the onChange event, so I added this extension method:

public static void FireChange(this Element element)
{
    element.DomContainer.Eval(string.Format("$('#{0}').change();", element.Id));
}

 

and this to my test:

_currentPage.RoleLevel.Select("Other");
_currentPage.RoleLevel.FireChange();

 

and it worked great!

Mar 132012
 
The actual first computer bug, a moth found tr...

Image via Wikipedia

DANGER! DANGER! DANGER! You’ve sent your stuff to QA for testing. What horrors will we find in the wild?

Chicken Little

Known Aliases: Teacup Storm, Spaz

Reported Bug: The e-commerce portion of the site is completely non-functional.

Actual Bug: Someone misspelled the word “shipping” in the second paragraph of the checkout page.

In the story, Chicken Little is a panicky creature who overreacts to very little data. Occasionally, this is also the case with a Chicken Little QA tester, but more often than not, this variety cannot tell the difference between “has an issue” and “unshippable.”

Every little flaw is a show stopper, and this overblown method of reporting defects often obscures what the actual defect is.

The Monarch

Known Aliases: Dalek

Reported Bug: The validation error messages should be a redder shade of red.

Actual Bug: There is no actual bug.

The Monarch loves the label “defect” instead of “bug,” because he believes that, if his personal opinions about the product aren’t met, this is the same as a defect.  The Monarch loves to log defects about colors, verbiage, where buttons should go – things that have no bearing on whether or not the software is actually working or whether or not any business users / clients agree.

There is no reasoning with a Monarch, and if you ignore the “defect,” it will continue being logged in the hopes that you will eventually be worn down through sheer backlog attrition.

Yoda

Known Aliases: Mufasa, Movie Mentor

Reported Bug: Broken, a screen is.

Actual Bug: Who knows?

Yoda reports defects in aphorisms, riddles, and vague statements. If this were the real Yoda, he would do this out of a desire for your self-improvement. In the QA field, this happens for reasons that can only be described as mean-spirited.

Interacting with bug reports from a Yoda QA tester goes something like this:

Yoda: An error, the screen showed me.

You: What was the error?

Yoda: Remember the error, I do not. Screenshot it, I did not. Write it down, I did not. Trust your feelings.

You: Can you at least tell me what you were doing when the error occurred?

Yoda: Walk your own path, you must.

Working with a Yoda, ironically, leads to a very high incidence rate of turning to the Dark Side.

The Grand Architect

Known Aliases: Monty Haul, Horn o’ Plenty

Reported Bug: Users should get a confirmation email when they check out.

Actual Bug: There is no actual bug.

The Grand Architect cannot differentiate between unmet requirements and new functionality. To make matters worse, they have a seemingly infinite reservoir of new functionality to offer.

The Grand Architect is a very dangerous form of QA tester because many times, their ideas are good ones. The problem isn’t the ideas; the problem is that they get logged as defects to a feature rather than being considered new features that should be sized and prioritized along with everything else in the work log.

This often leads to features never actually making it to production as the development team works overtime to correct “defects” such as the failure to show an animated, spinning head shooting lasers out of its eyes whenever someone buys something.

Nessie

Known Aliases: Singing Frog, Art Bell Guest

Reported Bug: I swear this was broken a minute ago.

Actual Bug: Probably a mental one.

Nessie experiences bugs that cannot be verified by anyone else at any other time, including themselves. They can produce no evidence this bug ever occurred, but they are positive that it happened to them.

Nessies are tricky because, if they are correct, the problem is a circumstantial one that is difficult to track down but absolutely should be fixed. If they are incorrect, days can be wasted as the team attempts to trace what could possibly be causing this problem.

Good QA Testers

Known Aliases: Unicorn, Angela

Reported Bug: When I was on Screen X, I did the following sequence of actions, and it resulted in the following error. Please look at the enclosed screen shot. This happened Monday morning around 9:30 am. I consulted our business users, and they confirmed that this is an edge case that does happen, although it isn’t that common. We should fix it, but it might not be as high a priority as finishing the current feature the team is working on.

Actual Bug: Um, wow. Really? Um, yeah, I guess that is the actual bug.

Good QA testers are rare as hen’s teeth.

Part of this is the fault of developers. Testing practices among developers tend to be so poor that QA testers spend the vast majority of their time making the software just work. Hardly any time is dedicated to testing actual business exceptions, working with end users, coming up with possibilities for new features, assisting in prioritization, etc.

A Good QA Tester can reproduce her sequence of steps to test a feature. A Good QA Tester knows the difference between a requirement not being met and Everything Else She Might Think Of. A Good QA Tester is collaborating her findings with the business users and the people who prioritize the work log. A Good QA Tester is part of the development team, not a completely separate entity who exists outside the team’s boundaries. A Good QA Tester reports an error with as much detail as she can muster and provides as much evidence as possible.

A Good QA Tester has taken ownership of her position. She isn’t just someone who checks off steps of a script and yells when something doesn’t work. She is part of the team. She makes sure the business users are getting everything they asked for. She participates in generating ideas for improvement and helps them work into the team’s normal work flow. She discovers legitimate business exceptions that may not have come up in the original analysis and makes sure they are accounted for. She tries to break the system the way a user might. She can tell the difference between “likely” and “unlikely,” “important” and “unimportant,” and “actual problem” and “my preference.”

If you have the fortune of encountering a Good QA Tester in the wild, cherish the experience.

Dec 122011
 
English: Example of a relational database tabl...

Image via Wikipedia

There’s a lot of popular misconceptions about how NHibernate Sessions work, especially things like the Save() and Update() methods, and what the ramifications are for Transactions.

Imagine the NHibernate Session like a container. When you load an object with NHibernate, it gets put into this container. Any change you make to that object anywhere, NHibernate knows about it. Those changes also happen in the container. They aren’t “disconnected.”

Let me say this a different way: If you use an NHibernate Session to Get() or Load() or whatever an object, NHibernate is now aware of that object and all of its changes until the Session is closed.

So, you might end up with two or three different objects or collections of objects in this container.

Most people use an NHibernate Transaction for everything, which is a good practice, considering that NHibernate uses an implicit Transaction for everything whether you specify one or not.

Here’s the kicker.

When your Transaction commits, NHibernate will take your objects in the container and synch up the database with the state of those objects, whether you have explicitly told it to save those objects or not.

This can seriously bite you in the butt if you’re not aware of it.

Trying to save some overhead by not loading an object’s child collections? It goes into the Session without collections, so when the Transaction commits, guess what? NHibernate will delete the child records when the Transaction commits, whether you have explicitly told it to or not.

Did you change some data in your object for display purposes? NHibernate will save that change back to the database when the transaction commits.

Now, the overwhelming majority of the time, NHibernate tracking our changes automatically is very nice and saves us from having to atomically manage every add, update, and delete on every single object. However, it is important to note that these changes will be committed to the database whether or not you have explicitly told NHibernate to do so.

Thankfully, for those times you’d like to manipulate an object and not have those changes synched with the database, NHibernate offers a very simple way to detach an object from the Session.

Session.Evict(yourObjectHere);

And then you can do whatever you want, but keep in mind NHibernate is now effectively “blind” to this object.

If for some reason you need to attach a disconnected object to the Session, you can do that by:

  • Session.Update(yourObjectHere); attaches a changed object
  • Session.Lock(yourObjectHere); attaches an unchanged object
  • Session.Merge(yourObjectHere); if the object exists in the Session, this will merge the changes from the detached object into the one in Session – otherwise, it behaves as Lock().

It’s important to note that this is not the case if the objects are sent over the wire somewhere else, such as via a web service. NHibernate has no way to know what you’re doing to those objects outside that system boundary, so for all practical purposes, your web service acts like a blanket Evict() statement for the client.

Nov 172011
 
WASHINGTON, DC - DECEMBER 14:   (L-R) U.S. Int...

Image by Getty Images via @daylife

His name was Lamar
He was a lame-o
Republican from Texas, run you over with his Lexus
He drafted a bill
With twelve co-sponsors
They want to stop piracy pain
But no one seemed to find their brain
They took the DMCA curse
And then they tried to make it worse
When Google has to police websites,
Sanity drives off in a hearse

At the SOPA
SOPA Cabana
As brilliant as Hannah Montana
At the SOPA
SOPA Cabana
Please don’t endorse it
(or try to enforce it)
At the SOPA
They killed the Net

The Net’s a network (duh!)
You can’t police it
It’s full of information supplied by the world’s population
Now, I believe in
Intellectual Property
But the price you pay for free speech
Is, sometimes, a copyright breach
No, it’s not an ideal thing,
But the alternative’s Beijing
Just for, like, five seconds
Could you try not to be so right wing?

At the SOPA
SOPA Cabana
The bad guys don’t wear a bandana
At the SOPA
SOPA Cabana
It just makes me jitter
To think of poor Twitter
If the SOPA
It kills the Net

Sep 212011
 
A mirror reflects Sarge and the Quake III logo...

Image via Wikipedia

The problem isn’t their work ethic.  Your developers work hard.  They often work overtime that you may not even know about.  They kill themselves to meet their deadlines.  They aren’t playing Quake when you aren’t looking.

The problem isn’t their intelligence.  Your developers are extremely smart people.  They have put themselves in an industry that is constantly changing, and the rate of that change will only increase.  They have to deal with abstractions and concepts that rival math, linguistic analysis, and other varieties of pattern-spotting and computational jobs.

The problem isn’t their industry knowledge.  Your developers are reading magazine articles, blog posts, going to conferences and Code Camps, books, and working on side projects at home to sharpen their skills and stay on top of things.

The problem with your developers is that they know there are better ways out there to do what they do, and they’d do them if they had someone to show them how to successfully implement them in real projects instead of just giving them theoretical knowledge and examples, but they don’t have that.

It will take them literally years to compensate for that – to claw their way up into a higher level of development skill and productivity – all for the want of someone just to show them how these fancy concepts like TDD, Interface-Based Programming, Dependency Injection, etc. actually work together to get a real project done.

That’s their problem.

Jul 212011
 

ReSharper is virtually the same thing as Visual Studio for me.  I’ve used the two together for so long that it’s very difficult to imagine the Visual Studio IDE without the ReSharper feature set.

One of the things that ReSharper will do is highlight for you when a method can be made static (or Shared in VB).  I’ve run across enough people who have wondered about the benefits or disadvantages of making methods static that I thought I’d help you out a bit: ReSharper isn’t actually suggesting you make your method static.

Oh, I know it looks that way, mostly because the ReSharper message is, “Method X can be made static,” but what ReSharper actually means is, “Are you sure you have Method X in the right place?”

The primary way ReSharper knows if a method can be made static is if your method uses no instance members of the class it’s inside, and if that’s the case, you should ask yourself why that method is in that class as opposed to, say, one of the classes that shows up in its signature.  Seven times out of ten, you’ll find that your method is much more at home (and more closely adhering to the Single Responsibility Principle) if it resides as a non-static method of another class, and the classes in the signature of the method or the classes in the calls to the method are a great place to start, because then you’d be using actual instance members.

For instance, if I have code, let’s say in a viewmodel or presenter or some kind of “getting the screen stuff ready” class, that looks like this:

private string FormatName(string firstName, string lastName)

{

return string.Format(“{0}, {1}”, lastName, firstName);

}

And I call it like this:

FullName = FormatName(customer.FirstName, customer.LastName);

And ReSharper suggests the method could be made static, it’s appropriate to consider whether or not I’m doing this right.  Perhaps FullName should be a property of my customer object, formatted the way I want.

If FormatName is of more general use than that, I might consider making it an extension method.  It’s a judgment call, certainly, but I’ve seen a lot of applications with static formatting methods that could have easily been made extension methods and rightly so.

It’s also possible that the method should go in a class full of static methods.  Utility functions are famous (or infamous) for ending up this way.  You want to be careful, because these utility classes often end up becoming dumping grounds for unrelated methods that don’t seem to go anywhere else, and they become more like miscellaneous classes than utility classes.  Still, classes full of related static methods do have their place.

Ultimately, I might decide I’ve got my method belonging to the right class.  Static methods do give a slight performance benefit in certain cases, so at that point, it’s usually a good idea to make the method static if it doesn’t hurt anything.  But this should be your last option as a result of a deliberate design decision; the fact that you can make a particular method static should be just the start of a conversation about the possibilities.

Mar 312011
 

I just did this, today, and it took me a jillion blogs to figure it out.  I hope this helps someone.

Without doing these steps, you’re very likely to get 404 errors for your web services even if you’ve done everything else right.  The main reason for this is that IIS out of the box won’t properly process your URLs without file extensions.  So, here’s what you do.

1.  For WCF REST, your deployable files will probably be your bin directory, a global.asax file, and a web.config file.  Do not follow advice on the Internet from people who tell you to make .svc files.  They are completely unnecessary for WCF REST.  Move those out to your virtual directory or whatever if you haven’t already done so.

2. Make sure the web application in IIS is running under ASP.NET 4.  Always a good thing to check.  Ok, now the real stuff.

3. Right-click on your web app under IIS, go to Properties, select the Virtual Directory tab, and click the Configuration button.  Click Add.  You should now be looking at the Add/Edit Application Extension Mapping dialog box.

4. For the first box, click the Browse… button, select “All files” from the filter dropdown, and browse to your .NET Framework 4 directory (maybe something like C:\Windows (or WINNT)\Microsoft.NET\Framework\v4.030319).  Select aspnet_isapi.dll and click ok.

5. For extension, you want a wildcard: .*  If the dialog box doesn’t let you get away with just putting .* in the box, I got it to let me by first typing in some random extension like .axl, then backspacing over the axl and typing *.  This basically tells IIS to process URLs without a file extension.

6. Make sure the “Check that file exists” box is not checked.

7. Hit Ok all the way back to the Properties dialog.

8. Click on the Directory Security tab.  Click the top Edit button.

9. When using default WCF REST settings, you can only have one authentication method active.  You probably have two checked and you should uncheck one.  Probably you should uncheck Integrated Windows (leaving Anonymous access checked).

10. Ok out of everything and restart IIS.  See if you can hit your REST urls.

Good luck!