Monday, November 4, 2019

PUT vs POST

The HTTP specification provides us with two verbs that confuse me pretty much every time I have to think about them: PUT and POST. Since I found a really good answer on SO for the difference between them and when to use each one, I thought I'd write up a blog post, include that link, and remind myself when I use each one.

Anyway, here's the answer I found that I like.

As far as when I use each one, I use POST when I'm creating new resources and don't want to specify their exact location (and I never specify the exact location when I send data to the server because I usually want the server or the database to generate an ID that will be used to identify the resource later). I use PUT when I'm replacing a known resource in its entirety. The HTTP spec defines that a PUT request must make no assumptions about what the caller wants, and should just take what was provided by the caller and apply it to the resource at that address. I use POST to update part of a known resource without replacing the whole thing.

Update: I've started using PATCH more often for updating parts of a resource without updating or replacing the entire thing. This is more semantically correct than using POST. I'll try to remember to update this with an actual code example of doing that once I figure out how I want it all to work.

Update 2: It turns out I've been using PATCH wrong. Per the spec PATCH requests are supposed to include a list of instructions on how the object should be patched. I found this article that helped me see the light, then these instructions for implementing PATCH "properly" in dotnet 5. I'll try to put up a full example when I get it all working and have time.

Update 3: I found time.

POST: /cars (to create a new car resource)
PUT: /cars/{id} (to replace the car resource with that ID)
POST: /cars/{id} (to update the car resource with that ID, but not replace it)
PATCH: /cars/{id} (to update some pieces of the car, but ignore everything that isn't present)

Thursday, September 12, 2019

Converting Strings to Enums

In my last post I showed how to use the DescriptionAttribute to specify a customized value for an Enum value and I promised to show how to convert back to an Enum. Here it is, the FromDescription string extension method. This time I did remember to get the link from the SO answer I got this from. Thanks, max!
   1: public static T FromDescription(this string description)
   2: {
   3:   var type = typeof(T;
   4:   if (!type.IsEnum)
   5:   {
   6:     throw new InvalidOperationException($"{description} does not match any of the enumeration values);
   7:   }
   8: 
   9:   foreach (var field in type.GetFields())
  10:   {
  11:     if (Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) is DescriptionAttribute attribute)
  12:     {
  13:       if (attribute.Description == description)
  14:       {
  15:         return (T)field.GetValue(null);
  16:       }
  17:     }
  18:     else
  19:     {
  20:       if (field.Name == description)
  21:       {
  22:         return (T)field.GetValue(null);
  23:       }
  24:     }
  25:   }
  26: 
  27:   throw new InvalidOperationException($"{description} does not match any of the enumeration values);
  28: }

Now that we have the extension method we can invoke it on any string, like this:
var contactType = "Phone Call".FromDescription<ContactTypes>();

Wednesday, September 11, 2019

Converting Enums to Strings

Yes, I'm aware you can easily get the string value of an Enum by using .ToString(). And that's great in many circumstances. I recently came across one where it was important to us to be able to translate an Enum to a custom string that included spaces (which you can't do with an Enum's value). I should have bookmarked the SO answer where I got this code from, but I didn't (sorry, Original Author, whoever you are!).

This extension method takes advantage of the built-in DescriptionAttribute. We decorate our Enum values with the DescriptionAttribute and provide whatever we want, like this:
   1: public enum ContactTypes
   2: {
   3:   [Description("Phone Call")]
   4:   Phone,
   5:   Email,
   6:   Chat
   7: }

Once we've decorated the Enum values, we'll need the extension method to get the description we just provided.
   1: public static string ToDescription(this Enum value)
   2: {
   3:   var da = (DescriptionAttribute[]) value.GetType().GetField(value.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
   4: 
   5:   return da.Length > 0 ? da[0].Description : value.ToString();
   6: }

Now we just need to use the extension method on our Enum to get the description we specified. Let's say we have a class that looks like this:
   1: public class Interaction
   2: {
   3:   public string UserName { get; set; }
   4: 
   5:   public ContactTypes ContactType { get; set; }
   6: }

If we wanted to get "Phone Call", "Email", and "Chat" returned (depending on which one was assigned in the class), we'd use the ToDescription extension method like this:
   1: var contact = new Interaction { ContactType = ContactTypes.Phone, UserName = "engineer-andrew" };
   2: var contactType = contact.ContactType.ToDescription();

Since we didn't use the DescriptionAttribute on Chat and Email, they'll default to just use .ToString() so they'd return "Chat" and "Email", respectively.
That's all there is to it. I know it's kinda simple, but I've used it a couple of times and my rule is to blog about those things. In the next post I'll show how to go the other way (take a string and find its matching Enum value).

Thursday, June 27, 2019

Keyboard Events in Angular

It's not uncommon to have a form listen for keyboard events. In Angular there are some nifty shortcuts that make this process easy... ish. First, there are some (mostly undocumented) shortcuts you can use to listen for common key press events (like ).
<input matInput (keydown.enter)="doSomething($event)">

I've seen this used (and used it myself) in lots of places. Today I learned you can also listen for compound key press events.
<input matInput (keydown.ctrl.enter)="doSomething($event)">

This isn't documented so I don't know exactly which keys you can listen for or what kind of cross-browser compatibility there is, but I know the two I've got here, as well as the ones I've listed below, work in Chrome 75. If one of the keys you want to bind doesn't work (I tried keydown.add and keydown.+ and neither worked) you can go with a HostListener. These are pretty easy to use, but from what I can tell (and trust me, it would not be the first I'm wrong) they bind to the window and are bound from the initialization of the component until its destruction so I try to be careful with these. If you do want to go this route, here's how you can do it. This listener "hears" the plus sign on the keypad as well as the combination of shift and equal (for the plus sign on the qwerty part of the keyboard).
   1:  @HostListener('window:keydown', ['$event'])
   2:  keyEvent(event: KeyboardEvent) {
   3:    if (event.keyCode ==== KeyboardKeys.Add || (!!event.shiftKey && event.keyCode === KeyboardKeys.Equal)) {
   4:      this.doSomething();
   5:    }
   6:  }

There's an open request for documentation of key binding on Github if you want to go comment on it or see what other people are talking about it. Hopefully they get something put together sooner rather than later because it's much easier to use that than HostListeners.

Friday, June 21, 2019

How to Recursively Walk the Directory Tree

I can't believe I've never written this up before. Like, I literally can't believe it. I swear I did this a long time ago. Oh, well. Whatever.

I frequently need to search all the files in a directory for a specific text value and I always end up rewriting the same code to do it. Well, no more! Here it is. It's based on a sample from Microsoft.

   1: private static void WalkDirectoryTree(DirectoryInfo root)
   2: {
   3:  FileInfo[] files = null;
   4:  DirectoryInfo[] subDirectories = null;
   5: 
   6:  try
   7:  {
   8:   files = root.GetFiles("*.*");
   9:  }
  10:  catch (UnauthorizedAccessException e)
  11:  {
  12:   Console.WriteLine(e.Message);
  13:  }
  14:  catch (DirectoryNotFoundException e)
  15:  {
  16:   Console.WriteLine(e.Message);
  17:  }
  18: 
  19:  if (files != null)
  20:  {
  21:   foreach (var file in files)
  22:   {
  23:    if (File.ReadLines(file.FullName).SkipWhile(line => !line.Contains("search string")).FirstOrDefault() != null)
  24:    {
  25:     Console.WriteLine(file.FullName);
  26:    }
  27:   }
  28: 
  29:   subDirectories = root.GetDirectories();
  30: 
  31:   foreach (var subDirectory in subDirectories)
  32:   {
  33:    WalkDirectoryTree(subDirectory);
  34:   }
  35:  }
  36: }

Thursday, May 30, 2019

Reset Remote Git Repository to a Previous Commit

I've had to do this a few times and I've had to look it up each time. Next time I have to look it up, I can just come here.

Let's say you've committed some changes on a task branch, pushed them up to your remote repository, and completed a PR into a main-line branch. Then you realize something needs to get rolled back. How do you do that? It's pretty easy, actually.

git log --oneline (find the commit you want to go back to)
git reset --hard [commit hash] (reset the branch to the commit you want to go back to)
git push -f (force push the branch back up to the remote repository)

This doesn't delete the commit that was made by the PR, but it does essentially abandon it. You could always record that hash if you wanted and then move back to it later, but that's not what I wanted to do here so that's not what I showed how to do. Hopefully this helps someone other than me.

Thursday, May 2, 2019

Introducing TDD to Your Organization

This blog post was originally published on the ThoroughTest website, back when that was a thing. As a co-founder and primary content contributor for ThoroughTest, I absolutely own the rights to this post and the source code to which it refers. I intend to reproduce each blog post here on my personal blog since the company is no longer in business.


We've heard from developers at several companies (large and small, publicly and privately held) that they're interested in implementing test-driven development, but they're not sure how to introduce the concept to their organizations. Below you'll find our preferred method for getting your fellow developers on board with you, then in our next post we'll explain how to convince management that it's a good idea.

First things first, you're a developer and you think test-driven development is the bee's knees, but your fellow developers don't. We need to get that out of the way right up front. If that's not you, then the approach we're about to provide may not be very helpful.

We've written before about some of the benefits of test-driven development and those are all good points to bring up to your fellow developers. But let's look at how we can target them a little more directly now. In our experience, all developers hate re-work as much as (or usually more than) any other part of their job so we're going to focus our pitch around re-work.

The first step in avoiding re-work is to really understand what you're building. It doesn't matter how rock solid your code is if you built the wrong thing in the first place. Test-driven development addresses this problem by forcing the developers to walk through the requirements of the product while they're writing their tests; before any code is written. During this phase developers can - and should - seek clarification from the product owner, which will lead to a product more in line with what the stakeholders want.

The next way we can avoid re-work is to reduce the number of defects in the code we do write. There are two ways test-driven development reduces the number of defects that make it to production. First, the fewer lines of code, the fewer opportunities exist for bad code and test-driven development reduces the number of lines of code by keeping the developer focused on delivering features that were actually requested. Second, when code is written using test-driven development there will be a complete suite of fully automated unit tests running at the end. Although this doesn't eliminate defects directly, it does ensure that what is written works as the developer expected. At this point we have code that works the way we expect it to, and does what the product owner wants it to.

The last step in avoiding re-work is actually part of the process of re-work. Despite our best efforts, most code will contain defects that get all the way to production and some developer down the road will need to fix them. Test-driven development protects those future developers by providing validation (through the complete automated test suite) that the bug fix doesn't introduce a new bug in a related area. However, test-driven development also has the added benefit of speeding up the bug fix process itself. When defects are reported from production they sometimes only exist under very particular circumstances that can be difficult to reproduce. When using test-driven development to fix a bug the first step is creating a test that proves the bug exists. Because our code is structured to facilitate testing we can more easily isolate reported defects. Once we've isolated the defect we can fix it, then run the test we already wrote to prove the bug is fixed. From there we can re-run the entire testing suite to make sure everything still works as expected and we're ready to move on from the defect and back to writing new code.

These are the reasons developers will be interested in trying out test-driven development, but you still need to create your argument in a way that gets their attention. We recommend something along the following lines:

"Using test-driven development will decrease re-work for all of us, giving us more time to focus on writing the cool new features we all like. The process can seem hard at first, but if we stick to it for six months we'll see fewer bugs making it to production, which will allow us to focus on more new features. Don't you hate having to switch gears in the middle of working on some cool new feature so you can go fix a bug in something you wrote a year ago, or even worse, something you didn't even write? Test-driven development can reduce the number of defects that make it to production AND allow us to more quickly fix the bugs that do make it out."

Most developers care about their code and they care about writing good code. Test-driven development is one more weapon they can include in their arsenal to write good code. You just have to help them see how test-driven development makes their lives easier and makes their jobs more fun. Hopefully, this approach will help you do that.