Refactoring Your C# Code Just Got Easier - Use This Strategy!
April 10, 2023
• 7,706 views
In this video, we walk through an example of how and why you can take advantage of composition to improve your code. Examples are in C# dotnet.
Want the source for this video? Check it out here:
https://github.com/ncosentino/DevLeader/tree/master/RefactoringCompositionDITesting
For more videos on programming with detailed examples, check this out:
https://www.youtube.com/playlist?list=PLzATctVhnsghN6XlmOvRzwh4JSpkRkj2T
Check out more Dev Leader content (including full in-depth articles with s...
View Transcript
today we're going to go through an exercise for refactoring some codes that we can take advantage of composition so you might be asking yourself why do we even care about doing this right so you might have heard about composition or seen the word kind of come up when you're looking at object oriented programming today's exercise will show you why that's valuable and some easy steps that you can take to refactor codes that you can take advantage of this this is a strategy that I use all the time in not only my hobby programming but also in all of the professional code that I write when I need to refactor some messy code and try to break it into smaller pieces for composition alright I know you're eager so let's go hop over to visual studio and get started so I put together a really simple
program for us to walk through today that demonstrates that we have a little bit too much going on in a particular method and why taking advantage of composition is going to help us out here now I wrote this comment here and I just want to say it out loud but I don't want you to focus too much on the very specifics of what's going on in the code we're going to walk through a lot of this is a little bit contrived and it's just so that I can demonstrate some different functionality and then we can walk through this example to pull the code apart so don't really focus on the fact that we're going to be saving out URLs to a file here we're really just focused on the techniques that we can use all right I'll just spend a couple of seconds walking us
through what this method does so at the beginning you'll see that I'm just doing some sanity checks on the inputs that are passed into this method and I tried to document each little section here with a comment that just says functionality because I want us to be able to come back to each of these the next part and this again is just a contrived kind of thing that I wanted to add but we're going to pretend that our system is only able to download from https URLs and it will actually try to help out the caller by putting https in front of the URL provided if it's not already there what I normally suggest doing this not at all but this is something that we're just going to try and extract so that we can work through trying to refactor for composition the next part
here is pretty simple we're just going to go download the HTML content from the URL afterwards we're going to look at just using a regular expression to pull apart the URLs that we see inside the HTML and you'll notice that I left a comment here saying is this regular expression actually sufficient for looking for these hrefs inside of the HTML well right now we don't know the answer to this unless you're really good with regular expressions and familiar with parsing but if you stay right to the end of this video I have a follow-up on how we can actually explore how we can do unit testing to make sure that this stuff works the last couple of sections are pretty straightforward in here we're just going to build the output that we're going to put into the file and finally the last section is just
writing that content out to a file so that's going to be the method and the class that we're going to pull apart and trying to use composition to make this a little bit cleaner for us to work with I'm gonna go make a new project in visual studio so we'll still have all the original code and you'll be able to check this out on GitHub afterwards this way you'll have both the original project and the refactored one and you can compare and contrast them on your own time so I've gone ahead and created a second project here so so that we can work through this refactoring exercise I've introduced a bit of a shortcut for us here and that's that I've actually gone through the code already like I mentioned and put these little comments that say functionality on them for your own code if
you're looking at methods that are something like this where there is a lot going on I'm just going to zoom out you can see that it's almost a hundred lines of code doing a whole bunch of different things this is something that I would recommend for you to go do essentially walk through the code looking at what different sections of that code do and see if you can group each section into different types of functionality and coming back to why we want to do this well when we're thinking about composition composition is going to allow us to have smaller more purpose-built classes so that we can go compose something that's a little bit more complex this allows us to isolate individual parts of the code and help focus on more of a single responsibility principle if you're not familiar with the single responsibility principle it
suggests that a class should only have one reason to change and the way that you can interpret this is that as the name suggests it should only have one responsibility if we look at this particular method we can see that there is so much going on and in fact it is nowhere near single responsibility principle guidelines so this is really important when it comes to being able to refactor code and have things isolated so that you know things aren't just breaking across the board and like I mentioned if you stay to the end this is actually going to really help us with testing so I have another video that you can watch right after this so the first step that I recommend you do is go through your code trying to document the individual pieces of functionality you don't necessarily have to go write comments
like I've done and in fact I wouldn't go add these kind of comments and then commit them or something like that but the exercise itself is really about documenting the different sections so instead of walking through all this code again because I've just done that with you you can just keep in mind that I've gone ahead and grouped the individual pieces of functionality so what's the next step that we're going to want to do to refactor so that we can get closer to a composition pattern what we actually want to extract the functionality that we have here into different methods so if you're using visual studio like I am you can actually select this code right click on it go to Quick actions and refactorings I realize the text is quite small but it's generally the top context menu item and when that pops up
there should be an option saying extract method you can go ahead and click that and it will go extract that and you can give it a name for this example I've just called the first piece of functionality normalize URL something to keep in mind as well is that that context menu does not always work depending on the type of code that you have but you can of course do this work manually by trying to literally cut the code out paste it into a new method and then massage the actual parameters that you need to pass into that method so that it works what I'm going to do from here is actually repeat this process for the other pieces of functionality that we have in this class thank you foreign I've edited the video and actually have done this refactoring for us and if I scroll
down you can see that I have all of the methods that I extracted using the same approach that I just Illustrated and I've used the extract refactor tool to actually pull these methods out into the class so if I zoom out a little bit on the original method that we have it's now been reduced greatly to actually just have several of these method calls that do individual jobs for us at this point though we're still not taking advantage of composition so we have one more step to go do for each of these methods recall that composition is actually making smaller objects and then passing those into larger objects to compose the more complex objects that means that we're going to have new classes for these pieces just a side note that if you're following this type of approach you might find that over time you
create tons of individual small classes so I just want to pause to say that as you're doing this kind of thing you may want want to consider that you have classes that do similar types of functionality and it might make sense to merge them together so for example if you had a bunch of stuff that was helping to parse and format HTML perhaps you might group that into its own class instead of having 10 classes that go do something very similar for this particular example I'm actually going to make one class for each of the methods that we extracted I'll do that refactoring and edit the video so that you can see the result alright I've gone ahead and actually taken the methods out of this class you'll see that Visual Studio is now complaining because these methods don't exist in this class anymore if
I scroll down you'll see that I have these individual classes added here and these are just the methods that were in the original class that we pulled out and now add it into individual classes below I'd actually argue that the hardest part about this whole thing is actually coming up with good names for things so once you get in the habit of actually following this pattern you still might get totally stumped coming up with names I'll scroll down just a little bit more so you can see the other classes but these are all of the pieces that we had in the original method just pulled out into individual classes alright let's look at the last step that we have to do to actually take advantage of composition so now that we have all of our smaller building blocks we actually have to leverage them inside
of our class what we can do is actually create a Constructor for this class awesome URL saver and then pass in all of the pieces that we need foreign classes that are awesome URL saver class needs to be composed of we can now use some of the refactoring shortcuts in Visual Studio to easily add fields for each one of these and have them assigned in the Constructor a side note is that if I would have declared them as Fields originally I could have just made a Constructor right at the beginning okay now that we have access to all five of these different pieces that are awesome URL saver class needs we just have to make sure that we're calling them properly so if we go to each of the methods that no longer exists inside of this class we can just call the corresponding class
that now has the functionality we need all right so I've gone ahead and added each of the instances that we need to call and I've done a little bit of formatting just to try and keep it all a little bit more aligned so that it might be easier for you to read instead of scrolling across my entire screen here you can see that there's now no more errors left inside of this method and if I check the error list there's only one more spot for us to go fix up and that's actually when we go create this object right at the top of our program when we go to compose things we now have to provide instances of all of the things that our object requires let's go ahead and instantiate all of the required dependencies for our awesome URL saver at this point we've
actually completed doing the refactoring so that we can take advantage of composition let's go ahead and run our program to see if it works alright it finished very quickly I don't see any exceptions here but we have to go check the output when I open the output file I can see that I definitely have some URLs that were pulled from my blog alright so that's a really simple process that you can follow and repeat on almost any piece of code to try breaking out pieces of functionality into separate classes so that you can take advantage of composition the first step that we looked at was actually going through the individual method pieces and looking at the separate pieces of functionality that you might want to call out from there we actually extract those methods and you can Skip and combine these steps because you can
actually take that method and put it right into a new class right away or you can go kind of pull those out manually first try and organize them and maybe group them into some smaller classes together from there we actually have to go pass in those new dependencies into our class so this is actually the composition part we're going to compose this object now and then we update our original method to call the new dependencies with the methods that we extracted the result of this is that we have smaller classes that we can work with that are actually more purpose built the next step that we're going to look at is actually being able to test this code and if you watch this video right here you're going to see that this makes it a lot easier for us to work with
Frequently Asked Questions
What is the main purpose of using composition in C# code refactoring?
The main purpose of using composition in C# code refactoring is to break down complex methods into smaller, more manageable pieces. This allows us to create purpose-built classes that adhere to the single responsibility principle, making our code cleaner, easier to maintain, and less prone to errors.
How do I start the process of refactoring my code for composition?
To start the process of refactoring your code for composition, I recommend first documenting the individual pieces of functionality within your methods. Look for sections of code that can be grouped together based on their functionality. Then, you can extract these sections into separate methods or classes, which will help you organize your code better.
What should I do if I end up with too many small classes after refactoring?
If you find that you've created too many small classes after refactoring, it's a good idea to consider merging similar classes together. For example, if you have multiple classes that handle similar types of functionality, grouping them into a single class can help reduce complexity and improve code organization.
These FAQs were generated by AI from the video transcript.