
Weekly Dev Tips
Weekly Dev Tips offers a variety of technical and career tips for software developers. Each tip is quick and to the point, describing a problem and one or more ways to solve that problem. I don't expect every tip to be useful to every developer, but I hope you'll find enough of them valuable to make listening worth your time.
Hosted by experienced software architect, trainer, and entrepreneur Steve Smith, also known online as @ardalis. If you find these useful, you may also want to get a free software development tip delivered to your inbox every Wednesday from ardalis.com/tips.
Latest episodes

Sep 11, 2017 • 6min
New is Glue
New is GlueBe wary of the new keyword in your code, and recognize the decision you're making by using it.Show Notes / TranscriptThis week we're going to talk about the phrase, "New is Glue". I came up with this phrase a few years ago and wrote a blog post about it, and have incorporated it into a number of my conference presentations and training courses on Pluralsight and DevIQ. The goal of the phrase is to stick in developers' heads so that when they are writing or reviewing code that directly instantiates an object, they understand that this is tightly coupling their code to that particular object implementation. Let's step back for a moment and talk about coupling, and then return to why tight coupling and the new keyword can be problematic.CouplingYour software is going to be coupled to a variety of things in order to function. Software that has no coupling is too abstract to actually do anything. Some things, like your choice of framework or language, are likely tight coupling decisions you're happy with because you've considered the alternatives and are satisfied that you can achieve your application's goals in the language and framework of choice. Other things, like the infrastructure your application depends on, might be tightly or loosely coupled depending on how you write your code. Code that is tightly coupled to a particular file system or a particular vendor's database tends to be more difficult to test, change, and maintain than software that is loosely coupled to its infrastructure. Although coupling is unavoidable, you want to make a conscious decision about whether and where you want to tightly couple your code to specific implementations, rather than having accidental coupling spread throughout your codebase.CouplersThere are typically three ways in which code references specific implementations in a tightly coupled manner. Each of these violates the Open-Closed Principle since functions that use these techniques cannot change their implementation logic without the code itself being changed. The first two are making calls to static methods and the closely related technique of referencing a Singleton pattern instance, particularly when accessed using a static Instance method (making this just a variation of the static method call). The third is the use of the new keyword to directly instantiate a particular instance type. Your application needs to work with certain implementation types in order to be useful, but the decision of which implementation types to use should be made in ideally one place, not scattered throughout your system.When is new a problem?Using the new keyword can be a problem when the type being created is not just a POCO, or Plain Old CLR Type, and especially when the type has side effects that make the calling logic difficult to test in isolation. If you find yourself instantiating a string or a DateTime in a function, or a custom DTO, that's probably not going to make that function any more difficult to test. The fact that you're gluing your code to that particular implementation is not a large concern, so you should recognize it but move on because it isn't a major risk to the software's maintainability.However, if you discover a function that is directly instantiating a SqlConnection that, during its construction, immediately tries to connect to a database server and throws an exception if it can't find one, that presents a much bigger risk. Without special tools, there's no simple way to test the calling code in a way that doesn't involve setting up a real database for it to try to connect to. Further, the lack of abstraction around the connection may make it more difficult to implement connection pooling, caching, or a different kind of data store. If you find code like this in your data access layer, implementing an interface, then it's probably fine and in the right location. If you find it in your business logic or UI layer, you should think long and hard before you decide it's a good risk to tightly couple to a particular data technology from this location in your code.Is new bad?The point of "New is Glue" is not to say that "new is bad", but rather to raise awareness. You should think about the fact that you're tightly coupling the current function or class to a particular implementation when you use the new keyword. In many cases, after briefly considering this, you'll conclude that you're fine with the coupling and continue on. But in some cases you may realize that you're about to add tight coupling to an implementation, and the current code isn't where you want to make that decision. In that case, you'll want to refactor your code so that it works with an abstraction and some other code is responsible for providing the actual implementation the function or class will use.What about in tests?Often, our unit tests become very brittle and slow us down when there is a lot of repetition in them. Repeatedly instantiating types to be tested within each test is a common problem. You can mitigate this issue by ensuring that your code for creating a class for test purposes in a particular way only exists at most once per test class, rather than once per test. You can easily achieve this by placing instantiation logic in setup or constructor methods of your test classes. You can further extract common construction logic from your tests by using the Builder design pattern and having common builder classes that all of your test classes rely on to create the instances they will use. With these approaches in place, changes to how objects are instantiated will require minimal changes in your tests.Show Resources and LinksNew is GlueTight Coupling, LEGOs, and Super GlueWeekly Dev Tips EmailSOLID Principles for C# DevelopersSOLID Principles of Object-Oriented DesignRefactoring for C# DevelopersRefactoring Fundamentals

Sep 4, 2017 • 6min
Guard Clauses
Your methods should fail fast, if doing so can short-circuit their execution. Guard clauses are a programming technique that enables this behavior, resulting in smaller, simpler functions.Show Notes / TranscriptComplexity in our code makes it harder for us and others to understand what the code is doing. The smallest unit of our code tends to be the function or method. You should be able to look at a given function and quickly determine what it's doing. This tends to be much easier if the function is small, well-named, and focused. One factor that's constantly working against you as you try to keep your functions manageable is conditional complexity (a code smell) - if and switch statements. When not properly managed, these two constructs can quickly cause functions to shift from simple and easily understood to long, obtuse, and scary. One way you can cut down on some of the complexity is through the use of guard clauses.A guard clause is simply a check that immediately exits the function, either with a return statement or an exception. If you're used to writing code such that you check to ensure that everything is valid for the function to run, then you write the main function code, and then you write else statements to deal with error cases, this involves inverting your current workflow. The benefit is that your code will tend to be shorter and simpler, and less deeply indented.Imagine you have a method that performs a subscribe operation, and takes in three objects: a user, a subscription, and a term. Naturally, you want to ensure that these objects are not null before you start working with them. One way to structure the method would be to first check if the user is not null. Then, inside this if statement, check if the subscription is not null. And in this statement, check if the term is not null. Now in this statement, we are in what is sometimes referred to as the "happy path" for the function. Assuming the values of these objects are otherwise valid, the expected work of the function can take place in this block. Each of the different cases of invalid inputs should result in an appropriate exception being thrown, though, and so these require else blocks. There will be an else block for the term != null check, another for the subscription != null check, and finally an else block for the user != null check. This results in a fair amount of plumbing code and complexity that adds to the noise of the function and obscures its true purpose - to subscribe a user to a subscription.Refactor to reduce nesting and else statementsThe first way to address this is to eliminate the need for the else clauses. You can do this by inverting the if checks and putting the exception throwing statements at the start of the function instead of at the end. The first thing you check is if the user is null. If it is, throw an exception. No need for an else clause and no need for a nested if statement. Move on to the next argument. Check it, throw if it's null. Do the same for the third parameter. When you're done, you have 3 simple if statements, none of which are nested, and no else clauses. The function now fails fast, and after the input checks, the happy path for the function is whatever remains.Refactor to use Guard helper methodsChecking for null arguments is a common enough task in strongly typed programs that you can probably encapsulate it in its own helper function. I use a common static class I call Guard which provides static helper methods for common scenarios. For instance, in the example I just described, I'm going to want to throw an ArgumentNullException with the name of whichever argument was null in each of the three possible cases. Thus, it's very easy to write a method I call AgainstNull that simply takes in the argument and the argument's name, and throws an ArgumentNullException if the argument is null. This exception will bubble up and out of the calling method. When you implement this in the scenario I described, you end up with code that reads like this:Guard.AgainstNull(user, nameof(user));Guard.AgainstNull(subscription, nameof(subscription));Guard.AgainstNull(term, nameof(term));You can add additional Guard helper methods for any other common cases you need to check for, such as empty strings, negative numbers, invalid enum values, etc.If statements can take over your functions if you're not careful, making them much harder to understand and thus much harder to maintain. Cyclomatic complexity refers to the total number of paths through a given function, and should be kept in the low single digits whenever possible. Using guard clauses is one simple way to tame complexity in your functions and keep them smaller, simpler, and easier to maintain.Show Resources and LinksGuard ClausesGuardClauses Nuget PackageWeekly Dev Tips EmailCode Smells and Refactoring CourseRefactoring for C# Developers

Aug 28, 2017 • 4min
Listen Faster
Listen (and learn) Faster
If you can do it without getting left behind, listen or watch educational content at a higher speed.
Show Notes / Transcript
I've always been interested in speed reading. As a child, it seemed like a super-power, since it would dramatically increase how quickly I could consume information, giving me more time to do other things. On a related note, I often have wished for a nice substitute for sleep that didn't have nasty side effects. But I digress...
Listening faster
If you're listening to this episode on a phone or mobile device, the app you're using most likely has an option to change the speed. I try to record these at a fairly measured pace, even if I'm otherwise animated or excited by the topic, because I want to make sure they're understandable even to those of you for whom English is not your first language. However, for those of you who can manage it, I encourage you to listen faster by adjusting the play speed to 1.25 or 1.5x, or even faster if you can manage it. If you're not sure how to configure a particular player, I cover a few options in an article on my blog about listening faster. Look for it in the show notes.
If you're in a web browser on the show's site, there should be a little 1x icon on the right side of the player. Clicking it will cycle you through different speeds. Give it a shot and pick one that's comfortable for you.
Watching faster
Of course, there's also a lot of great content online. Whether it's YouTube, DevIQ, or Pluralsight, you can learn a lot about programming and your career in software development from video content. Here, too, you can usually adjust the playback speed. By adjusting the speed from 1x to 1.5x, you can consume a 30 minute presentation in just 20 minutes. Over time, these gains really add up and can make the difference between you falling behind and you passing by others as you compete to be the best you can be.
Counterpoint
There are those who disagree, and feel that listening to content at 1.5x (or whatever speed you prefer) messes up the artistic intent of the author. A fairly recent article on The Verge is titled simply Stop listening to podcasts at 1.5x speed. I mention this mainly to disagree with it and to give you my permission, as the author and "artist" involved in this podcast, to listen faster.
There may be instances where some subtlety is lost, especially when you're talking about a heavily produced and edited show with multiple speakers involved. I'm going to strive not to be that subtle. My goal for these shows is that they provide you with small, useful, concrete nuggets that you can immediately apply to your work. If you can't consume this information at a faster speed because I'm using too much nuance and subtlety (and not because perhaps English isn't your first language), then I'm failing.
Once I've produced one of these podcasts, I'm done with it. My only goal is that a significant number of developers find it, listen to it, and find it useful. The more content you're able to consume, hopefully the more value you're able to get from it. To that end, I encourage you to listen at a speed that works well for you.
Show Resources and Links
Life Hack: Listen Faster
Stop Listening to Podcasts at 1.5x

Aug 21, 2017 • 4min
Check In Often
Check In Often
As a developer, you should be using source control. You should probably be using distributed source control. And you should check in, probably more often than you think.
Show Notes
No matter what specific tool you use for source control, you should be checking in your code to a source control repository. Right now, do you have code that you're working on (or were recently working on) that isn't checked in? How long ago did you check it out? If it's been more than a few hours, that's probably too long to go without checking in your work.
Why should you commit often?
The more often you commit your code to a central repository, the sooner you'll discover integration issues. This works best if you're using continuous integration, which we'll talk about later, but even without it, someone else on your team may discover an issue with your code sooner if it's checked in somewhere they can get to it sooner.
Committing is like ctrl-S.
If you grew up using word processors like Word, you've probably developed the muscle memory of hitting ctrl-S to save frequently. All it takes is for your machine or application to crash one time while you have hours of unsaved work for you to realize that you really should be saving all the time. The more often you commit your code (and ideally, push changes off your local machine), the better off you are if the unthinkable happens to your machine.
Recovering from dead ends.
Of course, an even more common use for frequent commits is that they let you jump back in time when you find that you've gone down a bad path. This, in turn, can give you more confidence to try different approaches to problems or more ambitious refactorings, because you know you can easily jump back to a known good state at any point. One of my favorite sayings is a Turkish proverb, "No matter how far down the wrong path you've gone, turn back now." When you have an easy restore point to jump to, this is easy. When you don't, it can be tempting to keep fighting with an approach you know in your heart isn't great, simply because going backward is going to be at least as painful as struggling forward.
Don't use folders for version control.
Avoid the urge to use copy folder versioning. You know what I'm talking about. That copy of the code folder you made that appends today's date to it, that's sitting next to a dozen similarly named folders. That's not source control, it's undisciplined and sloppy. That's not to say I'm not guilty of doing it myself (this approach still gives me confidence when updating production code on a live server, for instance). But if you're regularly using source control properly, you won't find the need to do this in your local dev environment.
When should you commit?
You should be committing your code whenever you've made some tangible progress. Fixing a bug, adding a test or two, implementing a feature, completing a refactoring, cleaning up a bunch of formatting issues. Each of these could easily be represented as a single commit. Now, whether or not all of these end up in your commit history after you merge your changes into the master branch is another question. But while you're actively working locally, it can certainly be useful to have this granular of a commit history available to you.
Commits are like game history
If you’ve ever played a video game that allowed saving checkpoints, you understand the value of frequently saving your progress. If you don’t, and something comes along and kills you, you’ll have to repeat a lot of effort to get back to where you were. Frequent commits in your code will save you from the unexpected just like frequent saves in your games do.
Show Resources and Links
The Copy Folder Versioning Anti-Pattern
Blog Post: Check In Often

Aug 14, 2017 • 1min
Overview of Weekly Dev Tips
##Episode 1: Overview of Weekly Dev Tips
What is this podcast about, who is it for, and how can you participate in it?
If you have questions or comments, join my mailing list and reply to the email you receive.