You Don't Need Enums - Refactor Away Enums In #csharp!
January 19, 2024
• 1,951 views
Enums in C# are easy for us to use, but often this means it's easy for us to use them ineffectively. While I don't like to say right and wrong for different things, I do like to point out pros and cons of different approaches.
In this video, we look at enum examples in C# and how we can refactor our csharp code to move away from enum usage altogether! Yay for refactoring!
Have you subscribed to my weekly newsletter yet? A 5-minute read every weekend, right to your inbox, so you can start your...
View Transcript
all right I'm back to talk about enums and c and if You' watched my other videos you probably think that I have something out for enums that I hate them that the the bane of programming existence in C it's just not the case I see a lot of misuse of enums so if you haven't checked out my previous videos I'll link the first one up here it's part of a series so far and if you watch the first two and come check this one out I think it'll make a lot more sense about where my perspective is coming from originally I shared some highlevel thoughts about enums in my perspective and then the next video after that I was focused more on what it means to be able to serialize and deserialize enums and some of the different options you have but when we went
through that we could see that there were a lot of complexities that were added for very simple things in this video we're going to look at a paradigm shift where we start with some code that leverages enums and then we're going to move away from that we're going to look at something that can replace using enums in your code base now I want to preface that this can't work in every every possible situation but if you start to think about your code and how it's interacting with things in this different way you may find that you're using enums less now if you're going through the series and it's starting to click with you and you agree with the concepts that I'm sharing about misuse of enums you may be able to go back and refactor some code and apply some of this now before I
jump over to visual studio just a quick reminder to check that pin comment for my free Weekly Newsletter and I'll have a link to my course there as well on refactoring let's check out this example I'm going to be looking through this product enum example and we're going to start with looking at some offering types here so I have a course ebook and a template offering type that I might have as different types of products or services that I want to sell in the previous videos if you've gone back and watch those you'll recall that we had a products enum so if I go expand that we can see that these were some different types of products and just to reiterate this is the type of pattern that I would not recommend you use because it's something that would be changing potentially quite quite regularly
I do recommend you try to reserve enum usage for things that either never change or change extremely rarely when we look at the offering type enum that I have on the screen right here highlighted from 27 to 29 these are three different types of offerings now this seems like it might change less than individual products and that's probably true however if I wanted to start offering a service like one-on-one coaching or I wanted to be able to offer you paid Discord access to my community those would be new offering types that I have to think about including into this enum so I want to walk through some of the code that consumes this we can think through what it means to start adding things into this enum how that code would have to change but I want to walk through how we might refactor some
of this code to move away from that enum usage a quick note that the code here is going to be a little bit contrived I don't have a fully built code base using enums in a way that I think is inappropriate if you're interested and you want to be able to share something like that with me please reach out to me I'm happy to make a video where we go refactor that I'm not going to pick on your code but if you want to volunteer it we can use it to go refactor all right so I have this product record here and we can see that it has one property on it that's called ID and then it has that offering type that we just looked at as well so just these two properties on this record now this product Handler that we're going to
go look at it's a pretty contrived class it's really lightweight but it is a little bit artificial but if we look at what it does it has this method called do stuff really because I'm bad at naming things and coming up with examples is tricky for YouTube but um the other thing I want to mention here is that some of the indentation you'll see is a little bit silly but I'm just trying to do that to fit that on the screen for you so um the product type being equal to a template or an ebook what we're doing here is making sure that we can go get a file name that we could go download and save that to so we're getting like a default file name and then we want to get a download URL so these are two types of resources that we
could be offering and if we want to be able to do something with them we need to know if it's going to be an ebook or it's going to be a template CU these are two types of things that would have these types of characteristics but if we go into this resources helper I'm trying to show you this by the way because I see code like this all the time where enums are used to do checks like this if we have this code now so this is inside of that we have a similar type of thing right so if the offering type is going to be a template or an ebook we might say okay like we know how to go handle that based on the type of the enum we know what to go do there's similar things where people are doing type checking
in general right like if object is this type then go do whatever um so in this case it's not an object type it's the enum we're saying if the product has this offering type let's go make sure in this case that we can get the download file like the default uh file name for it and the other example right up here again does the same type of thing where it's like we want to be able to check if it's a template or a book to get that download URL what's interesting about this I mean this example we probably would want to provide the ID or something else it's like I said it's contrived but the point I'm getting across is that we have a couple of different locations that we need to be doing this type checking or this enum value comparison so we have
template and ebook grouped together here template and ebook group together here um this we probably didn't need to add it like these would come back as null if they weren't handled but maybe to be safe we wanted to do some defense in depth and add this on top of it and we're stuck with three places now that do this type of checking if I were extending my product offerings so I want to give you an example we go back up here and I go you know what my courses right now are all online but I would like to add maybe some type of offline course course something downloadable you can go through maybe it's like a combination of an ebook but um it has uh something you can download it has quizzes and stuff like that you can do it all offline so I'm going
to go create this offline course if you watch the previous video one of the things that we saw is that it can be kind of Handy if you have to modify an enum to jam things at the end of it you're not disrupting the rest of the enum it makes it a little bit maybe less organized when you're looking at the enum itself but if you're serializing stuff maybe it's more helpful so I might say offline course and this is a new type of offering I have that's technically downloadable from what we just talked about so what I might go do is say well all of the spots that I needed to support this are these other spots where we have template and ebook I would need to go find all of them right so it would look something like going to add an or
condition here product type wa we have offline course I'll move my head out of the way there so you can see it a little bit better but then we take that and I'm just going to copy and paste it to save some time but we have to go put it in the other two spots as well right we have to go build out the rest of the logic here it's not product type it's offering type right so we need that here and we also need it in this third spot and now all of these spots that are doing something with being able to download a product or this offering we have support for it now but this is sort of the PA Paradigm that we look at when we're dealing with enums right like when we use enums we try to make everything enum Centric
and what I want to suggest is that we take a step away from focusing on the unique enum values I want you to start thinking about a little bit more like abstractions or characteristics of the things we're dealing with and I kind of hinted at what these things are as I've been talking through this I mean at least for the cases that I have on the screen and that we've been looking through now what's common between all of these templates ebooks and offline courses and it's a bit of a giveaway when we start looking at the logic that we have here like the method names these are downloadable resources that's what they are these types of product offerings have that characteristic now something that you could go do depending on how if you're thinking about your entities and Entity framework how this stuff is stored
in a database or something else what you could go do is maybe go back up to your um your record that you have here for product and you could go add properties onto this right you could have something that's like the download URL it could have uh the default file name when you're saving it you could go add that stuff right onto the product now you might say well Nick that feels pretty gross because you know what about the online courses those those don't have a download URL those don't have a default file name to to download to and you're right so I agree that would feel kind of weird now you could go do that you could have them be nullable and treat that however you'd like um I'm not here to tell you that's right or wrong it's probably not the option I
would pick if I had the luxury to um what I might do instead is think about separating that out into something else so I want to think about my code that's operating on downloadable things right downloadable offerings instead of just treating it as products everywhere checking the type of the product I want to be able to say if I have a product does it have downloadable characteristics about it and that's the difference I think instead of saying it's the product a b c and then having to come up with all these different variations that we keep tacking on especially if they're spread throughout the code base like not a good time try to think about does this product have this characteristic so I want to show you a slightly modified version It's similar type of setup here but it's slightly modified to be able to
accommodate for that and what we might start to see if I scroll down here is this downloadable resource record that we have now so this is getting into a bit of like domain modeling and stuff like that there's uh creators online that are infinitely better at explaining this kind of thing Derek Co Martin from code opinion is absolutely amazing at talking about this kind of stuff so uh I might be butchering some of the terminology and if you want you could do something like tag Dereck or send him this video and see if he'll he'll pick on it and stuff I I love to to hear his different thoughts and opinions so I wouldn't be uh I wouldn't be too upset if he if he hurt my feelings about me uh misrepresenting some of this stuff but I think that if you had a separate
entity to try and model this kind of downloadable behavior that could work really well and I think that it could help us move away from having these enums at least in this particular case if everything was focused on download in we could pull out that concept and have it as a downloadable resource so what I've done is I've just given this entity its own ID um you can kind of do whatever you want your modeling but this has a relationship back to the product whether or not the product has the relationship to this or this to the product or both ways outside of the scope of this conversation but you can see that now this entity that we're talking about this record has a download URL and it has a default download file name these were the the things that we were trying to codify
in the other parts of the code so the idea here now is that we don't need to go check for different types of product offerings we can simply go ask does our product have a downloadable resource associated with it and that's there's no enum right this this has nothing to do with an enum we've effectively moved away from needing an enum for that and to prove it to you I want to kind of go through this code example like I said it's going to be very similar I just added a two onto some of the names here but this do stuff method used to do some enum checking I said it might be a little bit Overkill and I I stand behind that I think that could still be Overkill but we've been able to do away with that so that's not so impressive but
you can see that I have this resources helper where we're getting a downloadable that means after we ask for that we should either have one or not so you can't see the intellisense but this get downloadable if I jump into it has a nullable downloadable resource that comes back so what we're able to do is given our product ID we could go look up that product and ask to see if it has a downloadable resource associated with it if it does and we could check that from the database right or have um if you wanted you could do some type of mapping in here and have your product list that doesn't feel very good to me but you could do that and not have an enum and be able to return a download able resource record right the enum has gone away so if it
exists and you have a downloadable resource record pass that back if not it's null and then we go back up here and then we can do stuff with that I mean if it was null we could return out or do some handling that we need to do we didn't really Define that in the other spot but if you have it then you can proceed to go operate on it and again the point of kind of showing you this is that we were able to go from having tock Tech is this resource or this product offering is it one of these types that we support and if we keep changing that we'd have to keep extending or modifying those lookups we just dealt with not having that at all right we started thinking about what's the concept of what we're dealing with here why are we
checking for that and the reason why we were checking for that in this case was because these were downloadable types of resources now I'm not going to go through more code because it's all kind of contrived right but if we think back to the rest of this enum what are some other characteristics or groupings that we might see right like I added offline course and we have course here maybe we have logic that operates on courses in general so what you might be able to do is instead of having this enum around still to be able to say you know if uh offering type is course or offering type is offline course and having that in a bunch of different spots you could say I'm interested in knowing if my product has characteristics of a course and you could have that as state as an
object or a data transfer object you could have a record representing that so you move away from having an enum and instead You' be able to go look up whether or not the product you're dealing with has some type of coor characteristic to give you one more flavor of that if I wanted to sell physical books as well right I'm not appending it in this case I'm just going to tack it onto the middle but I have two typ types of offerings that are book likee right so if I had logic in my code that was dealing with book likee things instead of saying offering type equals ebook or offering type equals book I could just ask for that characteristic the other important thing to mention here is that you don't need multiples right I don't need to say do I have an ebook or
a book in order for this kind of paradigm shift to happen and move away from the enum to this characteristic you know different Paradigm that we're talking about even for templates right if I have something like a reusable document that's a template sure I talked about try to Define that state as you know another entity a record and have all of the traits that are associated with template things as part of that so the point that I'm trying to get if I were to generalize it is that instead of building logic into your systems that need to understand the different characteristics of the enum instead I'd like you to think about pulling out those Concepts and separating them out into different things you can have that as state you can have different parts of your code different algorithms operate on that state you know those
different characteristics of the things you're dealing with instead of having them do something like look up a value match it if it's a match go perform the logic now I just wanted to say that I get that going through this example can seem a little bit tricky to rationalize and wrap your head around unless it happened to click and I know that sometimes using contrived examples can be like well Nick that's pretty artificial like that's not real how is this applicable so I get it um I'm just trying to find ways that I can walk through this and make sense of it so something else that I want you to think about if you're familiar with objectoriented programming Concepts is that this same type of thing comes up a lot I kind of hinted at it earlier in the video but instead of writing code
that says is this like is object of this type if so do these things instead of doing that we find different ways to structure our objects such that that logic is built into them right so that they're the ones that provide that to us or we put facades in place that know how to deal with that like we have different mechanisms to hide that kind of matching for us with enums it's the same type of thing it's just that I find based on the code that I've seen uh over many years this kind of stuff gets scattered this logical lookups get scattered everywhere and then when you want to modify the enum which I'm recommending you don't do but people always seem to set them up this way if you're doing that you have all of these spots to change and there's a lot of
overhead so I just wanted to give you this example so that you could walk through it with me see how you might be able to rationalize refactoring some of your code and if it makes sense to you going forward you can try to take this approach instead of just tacking on more enums and places so thanks so much for watching I hope this one clicked and we see you next time
Frequently Asked Questions
Why do you think enums are misused in C#?
I believe enums are often misused because developers tend to use them for values that can change frequently, which leads to complex code that requires constant updates. Instead, I recommend reserving enums for values that rarely change, allowing for clearer and more maintainable code.
What is the main alternative to using enums that you suggest in the video?
I suggest moving away from enums and instead focusing on the characteristics or abstractions of the items you're working with. By defining traits and behaviors directly in your objects, you can simplify your code and avoid the pitfalls associated with enums.
Can you provide an example of how to refactor code to avoid using enums?
Sure! Instead of checking if a product is of a certain enum type, I recommend creating a separate entity that encapsulates the characteristics of that product. For instance, if you have downloadable products, you could create a 'DownloadableResource' class that holds relevant properties, allowing you to check for those characteristics directly without relying on enums.
These FAQs were generated by AI from the video transcript.