Testing: A waste of time, or a HUGE waste of time?

I'm about sick of all this "wah wah wah, you should test your code" bullshit. Really. I mean, testing code should only be considered if any of the following apply:

1. You're a retard

That's the only condition. If you're a developer worth a crap, you know how to write code. Real developers write correct code the first time. It's that simple. If you can't write code that doesn't break ever, you shouldn't be writing code.

What's worse than bothering to test your code? Writing actual TEST PROJECTS. FLAMING NERD FACES, what the hell are you people thinking? Then, you get bugs IN your test projects. So then you have to write test projects for your test projects. I once saw a development shop that had five layers of testing projects. For reals.

The simple point is, a software developer is measured on output alone. If you're too busy "testing" your "code", you aren't producing. And you have to produce. I mean, you wouldn't pay your grocery clerk to test your apples before you bought it, would you? Hell no! That's your apple, dammit! You're wasting people's money when you bother to test code. If any idiot users think they found a bug, that's what they get for being idiots and not knowing how to use software. I mean, software can't be made to handle every possible case anyways. Everyone knows it, that's why there's nothing out there done to try counter it. So, if you concentrate on making your software work really well for one case, then you're set. They do it that way, and every time, it'll work awesome.

"So, what do I do about all my broken software I've done so far? I've wasted tons and tons on testing, that never got anywhere, because all it did was find bugs! I wish I'd never have tested anything, then we wouldn't have those bugs!" First off, I didn't ask for your stupid questions. Second, shut up. I'm about to give you the step-by-step process to fixing your project.

Step 1: Well, the first step in recovery of your failing test-ridden project, is deleting all those unit tests. Doesn't that feel good? It's like picking off scabs. Very cathartic. Next - start writing new, awesome, perfect code. It's simple. And as soon as you finish each module, immediately push it to production. Soon, your users and managers and all those other jerks we have to live with but don't actually provide any value at all will be so enthralled with your new code, that they won't even have time to remember your old crap. And if they think they find bugs in the new code? They're wrong. Plain and simple. But if they just won't shut up about it - go back to the beginning of Step 1, and repeat.

That's right. My step-by-step process only needs 1 step. That sure as hell is alot easier than all those steps to test things. And easier is better - Steve Jobs has shown us that (too bad MS is full of idiots and won't let .NET code run on Macs - really pisses me off they block off mac users specifically. You know all they have to do is flip a "run on non-windows" switch, and it'd work. Buncha jerks.)

"Wow Rob, thanks alot. You've really opened my eyes." I prefer praise to be made monetarily, but I'll let it slide this time.  Remember, code fast, code hard, code voluminous. Everything else becomes a blur when you're raking in the cash, are being awesome, and being adored by the rest of company for shipping so much product.

YOU'RE WELCOME.

Idiot-proof guide to a Templated Control

Here comes the easiest tutorial ever for writing your own ASP.Net templated control. But first, you may be wondering "Why would I want to do that?". God I hate you. So much. You and all your damn questions.

Anyways, these are great when you want a reusable control, with common functionality, but you don't actually want to enforce a certain layout, or limit a developer in what they can actually show on the control. Anything can go inside the templated area - html, pictures of cats, asp controls, more cats, you name it. You like to use the ListView control? That's a templated control. You like to use UpdatePanels? That's a templated control. "Wow Rob, all the cool controls use templates!" Yep. And you want to be cool, don't you? Of course you do. You're not an emo terrorist.....ARE YOU!?!?!

So, here's the basics. This examples provides no use whatsoever to anyone ever. We're going to make a control that doesn't do a damn thing but host a template. So, we'll start by making our control. This is the easy part. You can do this with a user control, or write your own control from scratch. All you need is a class that inherits from the Control class, but I'm going to be inheriting from UserControl for this example.

   1: public class WorthlessControl : System.Web.UI.UserControl
   2:     {
   3:         protected void Page_Load(object sender, EventArgs e)
   4:         {
   5:  
   6:         }
   7:     }

If you're already confused, sorry. No, I'm not saying I'm sorry that you're confused, I'm saying you're sorry, and I loathe you. Or whatever.

Next, we want our control to hold the template, right? That's kinda the whole point. We don't define a specific template class, however - there's an interface called ITemplate, that we'll be using. Lets name our property something useful, like ContentTemplate. I know, I know, you really had your heart set on KittyCatJunction, but maybe next time. So, we'd write something like this:

   1: public class WorthlessControl : System.Web.UI.UserControl
   2:     {
   3:         [Browsable(false)]
   4:         [PersistenceMode(PersistenceMode.InnerProperty)]
   5:         public ITemplate ContentTemplate { get; set; }
   6:  
   7:         protected void Page_Load(object sender, EventArgs e)
   8:         {
   9:  
  10:         }
  11:     }

"HEY WAIT A MINUTE THERE ARE BIG WORDS THERE YOU DIDN'T WARN ME ABOUT AAAAHHHH!"

....my hate for you grows exponentially with every passing second. I don't know why I put up with you, seriously. You're lucky I can't stand to be alone. Alright, so those BIG WORDS are extra attributes We're putting on our template field. The first is "Browsable", and we're setting it to "false". Browsable controls wether or not it shows up in the properties window in the asp.net designer. Obviously, a template has no reason to be in there. The next is "PersistenceMode". It's an enumerated type, and we're setting it to "InnerProperty". What this allows us to do, is to write our asp.net markup now and use this property as a nested tag. Snazzy, eh? We don't want developers to actually have to do this stuff in codebehind. That'd be lamzorz.

"Sweet, we're all done! That was easy!" If you would stop yammering for FIVE SECONDS I could tell you were not done yet at all. Now, first off, our template needs somewhere to live. The template will, more than likely, contain asp.net controls. Now, each control that lives on a page has to have a unique name - else, asp.net has no way of knowing which control fired what event, and so on. For this, there's an interface called INamingContainer. It has no functions or properties you need to implement, but it lets asp.net know that it's going to have it's own naming space, and controls will be uniquely named within it. That's why ListView controls work - your ItemTemplate will get repeated many many times, yet you don't get things blowing up because it has 20 copies of "lblCatAwesomenessRating" defined. So, we'll define a naming container class for our templated property. It will also need to be a control, since it'll live on the page and all. Then, we'll need to tell our property what type of container he (or she, don't sue me) gets. It doesn't need to have anything else. However, if you were doing a databound control (which I will next time), this would be a good spot to put your data object - by convention, a property named DataItem. But we'll get into that later. For now, all we need is:

   1: public class WorthlessControl : System.Web.UI.UserControl
   2:     {
   3:         [Browsable(false)]
   4:         [PersistenceMode(PersistenceMode.InnerProperty)]
   5:         [TemplateContainer(typeof(WorthlessContainer))]
   6:         public ITemplate ContentTemplate { get; set; }
   7:  
   8:         protected void Page_Load(object sender, EventArgs e)
   9:         {
  10:  
  11:         }
  12:     }
  13:  
  14:     public class WorthlessContainer : Control, INamingContainer
  15:     {
  16:         
  17:     }

Hey, now we're getting somewhere. Almost. Kinda. Just *one* issue left - actually putting the consuming developers template to use. In most *real* controls, you'll probably have a PlaceHolder control that you'll attach to, but we'll get into that stuff next time (for reals - this is part 1). So, lets think about what we need to do here, hmm? We need to add controls to the page. What page lifecycle event sounds like a proper place? Why, that's correct! CreateChildControls! Maybe I'll call off that mob hit I put on you after all! So, we know where we need to do it - but what are we going to do? Well, the ITemplate class gives us a function called "InstantiateIn". That'll take our markup, and make it into real controls. It's like Pinnochio, but with developer crap. The function also needs to know, WHERE to instantiate all these wonderful controls defined in our template. That's where our Container comes back into play. We'll fire up an instance of it, and pass it in. We'll finish up by actually then adding our container, with our came-to-life template inside it, to our controls collection. So, here's what we have then:

   1: public class WorthlessControl : System.Web.UI.UserControl
   2:     {
   3:         [Browsable(false)]
   4:         [PersistenceMode(PersistenceMode.InnerProperty)]
   5:         [TemplateContainer(typeof(WorthlessContainer))]
   6:         public ITemplate ContentTemplate { get; set; }
   7:  
   8:         protected void Page_Load(object sender, EventArgs e)
   9:         {
  10:  
  11:         }
  12:  
  13:  protected override void CreateChildControls()
  14:         {
  15:             base.CreateChildControls();
  16:  
  17:             WorthlessContainer cont = new WorthlessContainer ();
  18:             ContentTemplate.InstantiateIn(cont);
  19:  
  20:             this.Controls.Add(cont);
  21:         }
  22:     }
  23:  
  24:     public class WorthlessContainer : Control, INamingContainer
  25:     {
  26:         
  27:     }

TADA! Pretty easy, eh? So, now if you want to use this on some consuming page or other control, your markup will look like this:

   1: <uc1:WorthlessControl ID="myWorthlessControl" runat="server">
   2:     <ContentTemplate>
   3:         Rob is so great!
   4:         <asp:Label ID="lblGreat" runat="server" Text="I love cats because they're awesome!"/>
   5:     </ContentTemplate>
   6: </uc1:WorthlessControl>

Just like you'd expect it to. Now, this control is obviously pointless, since it does nothing but expose a template then mimic it back to the page, but it gets you the basics of what's going on. You may want to have some of your own controls already on your control, like say some labels or something, then the custom area defined in the middle, that you can attach on to with a placeholder control. I'll start with that next time, then move on to your own templated databound control. It'll have MULTIPLE TEMPLATES OMG!!!! It's going to be SO AWESOME. You'll finally be as cool as your mom always said you were!

NULLS are your best friend!

Apparently there's a hate-monger spreading fear about the use of nulls. I'm here to tell you it's a bunch of bologna. And bologna is nasty enough as it is - this is old bologna you find behind the fridge that's been sitting right there on the radiator for 8 months.

Nulls are the best thing since sliced bread. The more we use them, the better everything gets - automatically. It's basically a "win now" button. "But Rob - don't nulls make bad things happen?" Hell no, idiot. Let a real developer speak for a minute.

There are so many super-awesome-beneficial things to nulls, that's it difficult to arrange them in order for presentation. So, I'm just going to have grab a few at random, and go from there.

1. Null is a short word.
This is super awesome. You know how much time is saved there? Tons. Let's compare:

if(something == null)

versus

if(something.trim().length == 0)

WOAH HOLY CRAP. I don't know about you guys, but my eyes got tired half way through that monstrosity. Saved time + saved brain power = saved $$$. Lots of it. Like, hundreds a day probably. Don't even get me started on keystrokes saved. I tried to count the amount of characters in the non-null example, but windows calculator had a buffer overflow and crashed. That's a lot of characters, I tell you. The first example has like, 7 or something. It'd be even worse if it was in VB, what with 500 combinations of AndAlso IsOr Maybe KindaSorta ButNotReally.

2. Null can mean ANYTHING!
This is super awesome too. If a database field is nullable, that means the value could possibly be null. Hell yes, sign me up! This is great for a lot of reasons. Let's think - what could a null value mean?

  • The data wasn't set by the user yet
  • There's no corresponding possible value that met what the user really wanted to enter, so they left it blank
  • For datetimes, it could be the timestamp for an event that hasn't happened yet
  • Maybe an application error happened and those values got lost
  • Someone let their kids play in the server room, and they damaged portions of the harddrive containing those fields

And this is just off the top of my head, people. That's a lot of kick-ass reasons. See, having this 1 option, "nullable", turned on for a column in a database, adds ten metric tons of usefulness to that field. With so many possible values, that column now goes from being boring old "Durrr I store 1 value" to "I contain a wealth of data AND metadata! Love me!"

3. C# has a null coalescing operator
Now, why would the geniuses at Microsoft put in an operator if it wasn't intended to be used? They deprecate bad things to help think for us. They are to software developers as Oprah is to housewives. Microsoft gave ADDED functionality just to make using nulls even easier! I'm not going to spit in their face by abandoning the use of nulls. Thank you, Microsoft Coder Guy. I will use ?? whenever possible.

Well, that's just 3 quick examples, and I'm sure other people have many more. I'd write more, but I'm working on a dynamic reporting system. Thanks to nulls though, my job should be half as difficult easy!

Good UI - It's not just a nuisance

I'm gonna hop on a soapbox. I mean, what's the point of having a blog if you don't rant and rave at least some of the time? I wanna yack about UI a bit. Now, I'm not a UI master by any means - but I do think that I've learned some good habits throughout the years. So, here's some of the things I've picked up - and I'm sure most of you probably know this already too. But I find it good for me to keep these ideas in the forefront of my mind when designing UI. It's all too easy to be lazy and crap out some generic unfriendly screens.

Why good UI is so damn important

This is one that I think some software developers seem to forget. The UI is everything to the user. Yes - we know that the biggest challenge seems to be just getting the software to work in the first place, but to a user? That has to be a given. If they don't even have confidence that your software will work in the first place, then you might as well as well print out all your code, delete the files, and burn the printed copies (just for symbolism). At that point it's useless. It kind of sucks that what for us is the most important part, is just flat-out taken for granted by users. And the second something doesn't work? That's when they fall back on whatever they used before - paper, or an old system. Since they pretty much want to do that anyways, so lets not give them any reason to.

So, when the underpinnings of the system take up the focus of a development effort, UI seems to be 'tacked on' last minute, in lots of cases. And that's just unacceptable. Remember - the UI is your user's ONLY connection to this software - it has to BLOW THEM AWAY. Sometimes, "just working" isn't enough. And honestly - if that's your high bar there, then there are serious issues elsewhere.

On top of this - software gets more and more complex every day. With each round of new and improved technology, the demands of the software produced with it grows. With all this extra functionality, presenting it to the user in a coherent, obvious, easy-to-use fashion is a SERIOUS challenge. Some think "Eh, anyone can design a UI" - wrong. Might as well say "any high school student can develop software". I mean, yeah, something can be produced, but it's liable to filled with bugs, short-sightedness, and be unfriendly both to users and future developers on the product.

So - UI is extremely important. Without good UI, noone will use our software, regardless of how robust it is underneath. What are some ideas, tips, and tricks we can encompass to make sure our UI is at least decent?

Visual cues

Reading is so 1999. If a user has to read a novel before they can figure out what to do a screen, they're going to hate your software. Clever uses of images and color that immediately signify what the corresponding action of information is will make your software seem like even a baby could use it! And given that oftentimes, our software is targeted to people who aren't very technically savvy, that's a very good thing.

For color, I find it's useful to use it to indicate a non-normal status. Read that again. That's a tip that was given to me by Dave Garcia - when developing Acuff, for balanced bills I would show green. For unbalanced, red. But, applying this rule, balanced bills show up as the default text color (in this case, black). The reason for this - balanced bills need no action taken. It's the unbalanced bills that are problems, and require an action. So, using color to signify something that is wrong, or out of the ordinary, can visually lead someone's eyes to areas they need to correct items. When things are fine, then just leave it as is.

With images...well...I'm not a graphic designer. Chances are you aren't either. I mean, yeah, I can fumble around in Photoshop (actually, I prefer Paint.Net - it's free. Purdon turned me on to it a while back). But you know who IS a graphics designer? Lots of nerds on the internet. Now - I'm not talking about images for your whole site (although, there are free website skins/templates out there as well), but for images relating to actions. And there are plenty of free icon sets out there for you to use. I find googling for "[action] icon" to be very useful. Like "edit icon" or "save icon". That's easy to do, you'll get lots of results, and looks alot nicer than a buncha text all over your screen. Sometimes you can find a set, then adjust the colors to match your site better.

The end result of all this? Your screens will looks cleaner and more focused. And to the user, this makes it seem simpler. There's an idea of "positive whitespace" - that empty areas of a screen make it seem less confusing. <Martha> It's a good thing </Martha>

Lead the user

When your software is being used, at no point do you want your user to say "Well now what do I do??!??!!". If that happens, you have some work left. Remember - the goal of a user interface is to provide an easy-to-use mechanism to access all that cool functionality built underneath it.

On each screen that you develop, all options available to that page need to presented in a clear and concise manner. This isn't always an easy task - but neither was all the work put in underneath this software, right? So why cheapen it. Take the time to do it properly. At each screen, put yourself in your users' shoes. What question will they ask themselves? Some of the obvious ones are "How can I change this data?", "What if I need to remove this data?", "Is there more detail on this data? If so, how can I get to it?". Those are the standard edit/delete/more-detail scenarios. And they can all be represented by images, yay!

But there may be some more complex scenarios as well. Like "Where else is this data used in the system?", or "I need to enter information that's almost exactly the same as this in another area". Digging out these scenarios that are applicable to your user base, and making the least amount of clicking/typing as possible for a user is where your UI can go from "well, it works" to "this actually helps me get my work done faster". And that's the goal we want.

One last bit - and this has caught on alot in recent years, but it's my blog, and I'm going to type it anyways, so live with it - is home areas. The first screen a user sees when entering your software is extremely important. This usually includes "jumping off" points, that lead a user to more in-depth pieces of the system. Another good idea is tracking what the user does - what reports do they run all the time, what searches are common, what specific object do they always look at. Then, you can present these as well as on the home screen. Home screens are also useful for "quick entry" things - like say time entry, or daily tasks, or quick notes. The home screen is the first thing a user will see - they don't need to go exploring menus to find out how to use your software. Your software needs to present them clearly and directly to the user. Overtime, that user may become more of a power user, and navigate the site purely by the menus - but first time around, it's our job to make what needs to happen obvious.

Present relevant data first

Now, I think this is an interesting one. I applied this to several places in Acuff. This is especially problematic when you're building software that accesses a pre-existing database, with years and years of data (which Acuff has). Sometimes, the list of data and options present in the database can just get incredibly huge. Now - we don't want to restrict the users ability to get to these items. But in cases where it's known that over half the options won't be used in 99.99% of the time, it's up to us to do what we can about it.

"But Rob, there's no way to know!" Shut up. Yes there is. The data is RIGHT THERE in front of us! A simple query to check in the database to see which options are used many many times will reveal it for us. Play around with the cutoff amount until you have a list that presents many options, but isn't unwieldy. Maybe also check by timestamps where applicable. Using this, you can extremely cut down that drop-down list or the amount of rows to page through. A simple checkbox with "Show All", and the user can then get the entire list. The user does less scrolling, their system "seems" less bloated, and they're happier. Everyone wins.

If it's even a slight annoyance to you, it's a huge problem

We're the techincal elite. Noone is more badass when it comes to using computers than us. I mean, not only can we use the stupid things, we can completely alter how they work! Holy crap! But remember - <BenParker>With great power, comes great responsibility.</BenParker>

What this means is - if you're developing your software, and if you find something that even bugs you just a little bit - CHANGE IT. FOR THE LOVE OF GOD CHANGE IT. I know it's extremely tempting to just "let it slide". I mean, after all, it's just one extra button click, right? CHANGE IT.  Let's just break this down to actual numbers. Let's say it takes 30 minutes for you to alter something that only removes what takes about 5 seconds for a user to do. Seems like kind of a bad trade-off, right? Wrong. Your user is going to see that repeatedly. Over, and over, and over, and over...and this will build resentment. Soon, the user will focus on how many times throughout the life cycle of this software they've had to click this extra button for no reason, when the software knew the intention of the action. Then, they're hating your software again. It doesn't matter that it works underneath. They're now annoyed, and your software is complete crap in their mind. Those 30 minutes pay off in spades, when a year later, they still love using your software.

Another good example is pre-population of data. Why have the user reenter all the information, if 90% of it already there in the system? The ability to copy->modify->save will make your users' head explode with happiness. There are of course cases where you want to make sure the user re-enters everything, but in cases where this isn't a problem, do it. It makes them happy. And happy users give us their money.

We're used to these things. We deal with annoying ass software all the time. We just deal with it, and move on. But if we raise the bar for what we produce to circumvent these issues, instead of just accepting it as "the standard", then we enter a whole new level of software. One that doesn't annoy the shit out of everyone.

Alerts - only for when things go bad

This is just a small pet peeve of mine. Alerts are distracting, obnoxious, attention-getters. Now, when there's an issue that needs direct notification or attention, then they're perfect. But restrict use of these to fatal issues. Like if a save fails, or connection is lost. But when things go as planned? Stay the hell away from them. If you feel that the fact that your application managed to successfully carry out it's intended function is so monumental that you need to bring your application to a halt, block the user from doing anything else, and have the user then signify this momentous occasion with manual input, then you probably shouldn't be writing software. Remember - they need to be confident it's going to do what it's supposed to do in the first place. They NEED to take it for granted. They shouldn't be concerned about it.

Now - keeping the user informed with up-to-date status is generally a great idea. But pop-up alerts are NOT the solution for this. Typically, labels on the matching screen, or perhaps a persistent status bar across the whole application is much more desirable. It's bad enough if the user has to do extra clicks when things go wrong. Don't make them have to do it when things go right as well.

Copying - how to make friends and save money!

Guess what? As much of a genius that I am, I'm not the first person who thought "Hmm...UI is pretty important" (probably more like third or fourth). But these first people, and their companies, that realized this, have invested a metric crap ton of dollars and cents into researching this. So, why not benefit from their hard work? This benefits us in two great ways - 1. Saves us time (and thereby money), and 2. Users are familiar to it.

If you're trying to come up with an interface for something, take a second and think about if you've seen a similar scenario in popular software. If that software is popular, usually that means users like it, which means it has a interface that doesn't suck. We don't always have to reinvent the wheel. However, there's also a chance here to bring your software to the next level. Instead of working on your own to make your software "standard", you start off with it being the standard. Then, using your (and your users) past experiences with this popular software, you can easily identify whatever interface annoyances may be present in them, and fix them. Now your software is a step up, AND recognizable. This saves training and acclimation time for your user. Booyah.

Plus, with using this popular existing software as a base, your users will immediately feel familiar with how to navigate around. You'll have your own twists and improvements, of course - but it keeps them from feeling like they're stepping completely into an unknown. This helps them make the transition, and gets them using your software faster. And the faster their using it, the sooner they forget about whatever old process they relied on.

But be careful with this - remember just to keep it "where applicable". A good obvious example, is the Microsoft Office suite. If you have an application that deals with files, some simple things like having the file name in the title bar, and typical options like 'load', 'save', and 'save as', are readily apparent as good fits. Don't skimp on these.

Rob sure does yammer on

Shut up. Now, I know I'm not perfect, and there are parts on my current project where I want to go back and make some adjustments. And I will. There are also lots of places where I've applied these ideas, and more, and I think they've lead to a decent, easy-to-use system. I think we all too often short-cut the UI, and that causes a project to fail. To be done right, it needs a large amount of time investment, and shouldn't be just quickly tossed out there.

I'm sure you guys have even more good ideas, so let's hear them! Or, tell me how full of crap I am, and everything should be out-of-the-box datagrids.

AAAAAAAAAAAAHHHHHHHHHHH

This will be my blog about blog stuff and things. And yeah, not digging the template. I'll see about redoing it later*. *probably never

Designed by Posicionamiento Web | Bloggerized by GosuBlogger