Saturday, May 2, 2015

Loose Coupling FTW!

I got some bad news today: a service I was using stopped working. I have some good news, too. I was able to fix my application in just a few minutes because I had loose coupling right where I needed it.
A new class and a change to 1 line of code, and I was back up and running!
Here's the extent of the new code. First a new class:


Then I just had to swap out one line of code to use the new provider:


And that's it. Let's look at some details (and planning) that made this possible.

Never a Good Time for Bad News
I sat down this afternoon to make some changes to my application that controls the lights and air conditioning in my apartment. Earlier in the week, I changed the persistent file format over from CSV to JSON (I'll write about this in a future article). Then I started working on a visual editor for the schedule to make things easier. I tried to continue that today when I came across my problem.

If you'd like a history of the application up to this point, check out this series of articles: Rewriting a Legacy Application (which also includes links to the GitHub project).

I fired up my editor application to see what it looked like, and it didn't come up. It just hung. This was a surprise since it was working just fine yesterday. But there is one thing that I don't have control over: the service call to get sunset and sunrise times.

After debugging through the application, I found the problem was the service. I tried to service directly and got the following message:


That's not something you like to come across. So I had to fix this before I could go on.

Alternate Calculation Available
Back when I was working on the time calculations, Matt Johnson mentioned a NuGet package that would possibly work for this. I figured that I would look into this if the service became an issue.

Well, the service became an issue. So, I took a closer look at Solar Calculator. And it turned out to be much easier to use than manually parsing the service data and converting things to local time.

I copied the sample code in the documentation and plugged in the numbers that I needed. The result was a pretty simple class (compared to the 80 lines of code I had in the provider with the service):


The SolarTimes object has what I need, and I just pass in the date and location (latitude/longitude) similar to the parameters of the service. But as you can see the parsing is minimal.

Note: I haven't looked at this code very closely; I was primarily focused on getting things working again so I could continue development. I'm pretty sure there is an easier way to do the time conversions (such as using "local" time rather than the time zone). But this code works and isn't horrible, so it gets to stay for now.

[Update: 5/6/2015: I did simplify this code a bit (and learned about DateTimeKind). Check it out: Fun with DateTime.]

Loose Coupling Saves the Day!
Writing a new class to do a piece of functionality is never the hard part. The hard part is trying to incorporate it into the application. Fortunately, I had planned for this.

Since I didn't have control over the service, I didn't want to rely on it too heavily. So when I created the sunset provider functionality, I first made sure that I had an interface for it.


Since I had this interface, that meant that I could program against the abstraction (the interface) in the main part of my code. (BTW, I really like Interfaces for exactly this reason.)

The other thing I did was use Dependency Injection. My schedule object has a dependency on a sunset provider -- it needs to know how to get the sunset and sunrise times. But rather than hard-coding that dependency, I inject the dependency through a property. (BTW, I really like Dependency Injection as well.)

That meant that when I did a "Find In Files" to search for the old provider (SunriseSunsetOrg), I found exactly 1 match. And it was really easy to change that out with the new provider (SolarCalculator):


This uses a pattern known as Property Injection. We have a class with an ISunsetProvider property. If we do nothing, then we get the default value (which is SolarCalculator in this case), but we're still able to assign a different value to this property for testing purposes.

Everything Else Still Works
So after changing this 1 line of code, the application now uses the new, working sunset provider. In addition, all of the unit tests still pass. (The reason the tests still pass is because they mocked the behavior of the service rather than calling it directly.)

If you don't believe that this is all that I changed, feel free to check out the GitHub commit: Added new sunrise/sunset provider (old service discontinued).

This shows 5 files modified: 2 files are project related from adding the new class and NuGet packages; 1 file is the new provider class; 1 file is the property injection update; and 1 file is a test console app to do a sanity check of the functionality.

Thinking Ahead
When I put together an application (or add functionality), I pay close attention to the things that are likely to change in the future. In this case, I strongly suspected that I would want to change the sunset/sunrise calculation at some point. Because of this, I added a seam to my code -- a place to make it really easy to swap out one piece of functionality for another.

Adding the seam was pretty easy: just a combination of interfaces (abstraction) and dependency injection (loose coupling).

It feels really good to be able to take advantage of the loose coupling. Now I feel a lot better for having put it in to begin with. In addition, the new provider uses a calculation on the local machine so I no longer need a network connection to get that information.

Loose Coupling For the Win!

Happy Coding!

Saturday, April 25, 2015

New Video: Deciphering the LINQ Join Method

I really love using the fluent syntax with LINQ. This gives me full access to all of the very useful extension methods.

In Part 2 of the Lambdas & LINQ video series, we took some time to understand the parameters of the Where method and also OrderBy. After seeing this, folks sometimes ask me: "What about Join?"

And why do they ask this question? Because this is the method signature:


Yikes.

But when we break things down, it's nothing that we haven't seen before. And that's exactly what we do in my latest video: Deciphering the Join Method.



If you'd rather have a text version, check out this article: The LINQ Join Method: Deciphering the Parameters.

And find the other videos, links to code on GitHub, PDF walkthroughs, and other articles here: Learn to Love Lambdas (and LINQ, Too)

I'm looking to produce other videos based on my articles (so that different folks can learn in the way that works best for them). If you have a favorite topics that you'd like to see put into video, let me know.

Happy Coding!

Monday, April 20, 2015

New Video: Captured Variables & for Loops

Captured variables are a really cool feature of lambda expressions. But it can also be dangerous if we try to capture the indexer of a "for" loop.

In my latest video, we take a look at the problem that we run into when we try to capture an indexer. And we'll also see how easy it is to get around the problem. There's just one thing we need to keep in mind:
The value of a captured variable is the value at the time it is used, not the value at the time it is captured.
And if you need a reminder of what captured variables are, be sure to check out Part 1 of the Lambdas & LINQ series: Lambda Expression Basics.

If you'd rather read about this problem (and solution), check out this article: Lambda Expressions, Captured Variables, and for Loops: A Dangerous Combination.

Otherwise, watch it here (or on YouTube):



There's also a playlist to watch all of the videos in the series: Lambda Expressions and LINQ in C#.

For more links, articles, and to find the code on GitHub, check out Learn to Love Lambdas (and LINQ, Too) on my website.

Let me know if you like the videos. If so, there will be lots more coming. But don't worry, the articles will keep coming as well. Some people like text, and some people like video. I'm glad to provide both where I can.

Happy Coding!

Wednesday, April 15, 2015

Users Don't Fail; Designers Do

It's really easy to feel like a failure as a user: maybe we can't find a piece of information on a website; maybe we can't figure out how to enter some data; maybe we can't open a door.
Whenever you feel like a failure as a user, remember that you didn't fail, the designer did.

And this holds true when we are the developers: Our users don't fail; we do.
I've come across a few things that have made me think about this lately, and I'll talk about those in a bit. First, I need to tell a story about how I felt like a failure as a user.

Jeremy Gets Trapped on a Balcony
Several years ago, I was attending a convention at a local convention center. As often happens while working in tech, some issues came up at work. As I was walking along the hallway on the 2nd floor of the convention center, I got a phone call. So I answered the phone and headed outside to the balcony to take the call.

I was only out there a couple of minutes. But I ran into a problem when I tried to get back into the convention center. I grabbed the door handle, and the door didn't move. Crap, locked.

I grabbed the other door handle and tried it. Locked. Maybe I wasn't supposed to go out that door.

So I tapped on the glass to get the attention of someone inside. And I motioned for them to come open the door for me.

He looked at me, and while motioning with his arms, he said a single word: "Push".

Thinking About Affordances
So what makes me think about one of the not proudest moments of my life? I'll blame it on listening to a recent episode of .NET Rocks! UX Thoughts with Danielle Cooley.

I had the opportunity to meet Danielle (@dgcooley and http://dgcooley.com/) at the Nebraska.Code() event last month. User Experience (UX) is a topic that I've been interested in for a long time (you can see some of the books I've read on my website), so I was happy to have a chance to talk to someone who specializes in UX research and how humans behave. We had a good conversation at one of the evening get-togethers and shared experiences.

And I was reminded of my "failure" while listening to .NET Rocks!, first because she mentioned how users don't fail, designers do (and "designer" is whoever is doing the design -- probably a developer in a lot of cases). I was also reminded of a book that was *not* mentioned in the episode but is one of my favorite design books: The Design of Everyday Things by Donald A. Norman (Amazon link).

Norman mentions the idea of "affordances". He deals primarily with things in the physical world, and affordances are those clues that tell a person how something is supposed to be used. This can be the materials, the shape, the position of buttons or handles, or any other aspects of how an object presents itself to a potential user.

I really enjoyed reading this book, and it makes me look at things in the world in a different way. (I have the 2002 edition; I didn't realize there is a 2013 expanded edition, so I guess I need to pick that up.)

And if you're curious about the item on the cover of the book, this is based on the "Coffeepot for Masochists" designed by Jacques Carelman.

Norman's book contains a section about affordances on doors in popular architecture and how they can often fail the people who have to use them. And that's what leads back to my "failure" to use a door properly.

Analyzing the Failure
As you can imagine, as soon as I heard the word "Push", I was rather embarrassed. A simple push on the door freed me from my trap. And I could feel my cheeks start to burn.

Soon after, the analysis began: How did I get myself into that situation? And how do I prevent it from happening again? There were several contributing factors.

1. I was distracted when I went out the door.
I was on the phone and payed no attention to which way the door swung as I went outside. I was concerned with who I was talking to and trying to get out of the crowd of people.

2. Public building doors normally open out.
When we go into a public building, we're used to pulling a door open to get inside. Why? We can thank the fire codes for this. In event of a fire, the way out of the building must be as free from obstacle as possible. This means that doors swing out so that we can easily get out of the building in an emergency.

But this door swung in. Why? Because this was a balcony with no other exit. So in an emergency, the way "out" was to go into the building. So that's why this door opened "in" even though I was outside.

3. The designer went for aesthetics over functionality.
The door handle was a vertical bar. Let's see what Norman has to say about this:

From The Design of Everyday Things by Donald A. Norman

So, I wasn't far off here. The door handle looked like the one on the right (vertical bar that curved into the door). To make things even worse, the handle on the other side of the door was exactly the same vertical bar.

The designer had decided to go with what looks nice rather than what is easy to use. (And I'm sure it looks really great in pictures.)

Result: I was doing what humans normally do.
That's not something to feel bad about. I'm not the one who failed in this situation; the designer did.

Failing as a Designer
As a user, I should not feel like a failure; it is the designer who failed me.

As a developer, I need to take this same attitude toward my users. If my users can't figure out how to do a particular task, they have not failed. In that situation, I am the one who failed (as designer of the software).

There was one particular application where I failed as a designer. At the time, I knew I was failing as a designer. But there were ROI decisions to be made.

Let's get into some details. I worked on a calendaring application for a theme park. Every scheduled event went into this calendaring system: this included maintenance items (such as painting and repaving), publicity items (such as press events for a new ride), operational items (such as operating hours), and entertainment items (particularly shows and parades) -- and it even included special events like weddings.

The data entry screen that we had to enter these items worked for 95% of our users, and it worked pretty well. But it was very awkward for 1 user: the person from the entertainment area who entered the shows and parades.

I always wanted to write a special data entry screen just for this one person. She was constantly entering events -- there was *a lot* of entertainment at this location. We did have some templates to make it easier to duplicate items, but it never got to where it should have been to make entering these types of events easy.

So, in this case, I failed as a designer.

Mitigating Failure
The one good thing about this is that I was aware of the failure. Because of this, I spent extra time with this one user to make sure that she was as comfortable as possible with the awkward process. And whenever she ran into issues, I made sure to resolve them as quickly as possible.

I know that this extra effort payed off. The result was a good relationship with this user (and the department in general). In fact, when that person left the position and a new person came in, I found out that she spoke very highly of me to the new person. And I made sure to stop by their office to introduce myself and let the new person know that I was available to answer any questions.

Face-to-face conversations really help build relationships. I've been able to build trust with the people who use my software even when the software was not ideal.

Wrap Up
We have a big responsibility as developers: usually we are also the designers who decide how users interact with our software. And if our users end up "failing" when trying to use our software, it is not the user who has failed. It is we who have failed our users.

Think about the time that a piece of software (or a door handle) has frustrated you. Did you feel like a failure? Remember this when you're designing your own software. We want our users to be successful. And in doing so, we need to make sure that *we* don't fail them.

Happy Coding!

Tuesday, April 14, 2015

New Video: Declarative Programming with LINQ

I just published Part 3 of my video series on Lambda Expressions & LINQ in C#. This time around, we look at the difference between imperative programming and declarative programming.

Imperative Programming is what we're used to: we tell the computer *how* to do something. This usually involves giving step-by-step instructions such as looping through data, using "if" statements to make comparisons, and then doing the pieces of work that are important to our task.

Declarative Programming is a bit different: we tell the computer *what* we want done. Then we leave it up to the computer (or library) to figure out the rest. It turns out that we can use LINQ methods to make our code more declarative. And in doing this, we make our code easier to read and understand.

So be sure to check out Declarative Programming with LINQ:



This completes the basics of lambda expressions and LINQ. All of the videos are collected in this playlist:

Playlist: Lambda Expressions & LINQ in C#
I have a couple of bonus episodes planned (to cover some more details on captured variables and the Join method). So be sure to stay tuned for future episodes.

Happy Coding!

Monday, April 13, 2015

Talk with Dustin Davis on //c0deporn

I had a chat last week with Dustin Davis (@PrgrmrsUnlmtd) about one of my favorite topics: Lambda Expressions.

You can watch the video on YouTube: Getting Started with Lambda Expressions with Jeremy Clark



If you want to have a chat about technology, just drop me a line.

Happy Coding!


Sunday, April 12, 2015

New Video: Demystifying LINQ Methods

I just published Part 2 of my video series on Lambda Expressions and LINQ. You may have heard about Part 1 (Lambda Expression Basics) on This Week on Channel 9 (big thanks to Channel 9 for the mention).

A big problem with LINQ is the apparent chaos of the method signatures:


When we see this for the first time, it seems extremely complex. But once we dive into the different pieces, we see that things aren't as complicated as they seem. And that's exactly what we do in this video: Demystifying LINQ Methods:


While exploring LINQ, we mention a couple of other topics that are covered in separate videos:
As a reminder, Part 1 covers the basics of lambda expressions. And in future videos, we'll look at how LINQ can help us make our code more readable through declarative programming. We'll also take a look at the Join method and the intricacies of using captured variables in "for" loops.

Get links to all of the videos, plus code samples, additional articles, and a PDF walkthrough here: Learn to Love Lambdas (and LINQ, Too!)

Happy Coding!