Recently an intern on the team I am currently working on asked me to review the code on a new solution he has been tasked to code. About a week or so later, I received the following from him via chat:
On the project I sent you, I don’t understand what you mean by use a separate, reusable DLL. I’ve been trying to read about it, but I’m still not super sure.
My short reply to him via chat was:
Generally, model classes are used in multiple projects. For reusability of those models, they should be in their own separate DLL (C# Project). Not only is this good re-use, but also makes it much easier to unit test.
In all my code conference session, I preach the importance of coding for reuse, right from the beginning of the project. These days I state that 90% or more of any application code should be in re-useable assemblies (DLL’s), for many reasons that I will discuss. The only code in the actual app should be just enough to deal with the user or data coming into a back-end API. Not every developer will agree with this way of coding, but it has saved me a lot of time and produces more stable and reliable code and in the long run, saving the company money!
Don’t Listen to Your Boss!
One of the things I have been saying for a long time when thinking about the future of the app is “Don’t listen to your boss!”. Why? Well, as usual, I learn the hard way. One time back in the 90’s my boss assigned to me, a web project to code (back in the ASP days). I asked him “Will this always be a web project?”. He answered to the affirmative. So, I wrote the web site.
At some point later, he came to me with an urgent need to support another app type other than a web site. I told him; it will take a while because I would have to copy most of that web site code out to a DLL (VB), so the code can be used for two different apps. This was not the answer he was looking for. If I just didn’t listen to him and architect it correctly from the beginning, supporting a different app would be trivial.
Ever since that day, I stopped listening to my bosses, when it comes to the future of the app and always architect apps with code re-use in mind… always!
Practice What You Preach Dave!
Since that day, I always put most of my code in re-usable DLL’s, even my own apps and even in testing/ benchmarking apps. Don’t believe me? Let me prove it to you.
Windows App Solution Example
I’ve had an app for developers for a while now called the dotNetTips.Utility Dev App (I hope you will check it out). Currently, the app has two main features. I could have just put all the code in the EXE… but I didn’t, as you will see below.
This shows how I separated out the code into the different assemblies including the one’s (in the green box) that are part of my open-source assemblies (the first two available on NuGet). I will give a brief description of what is contained in each.
- Dev.Utility.App.exe (Clr C#): This is the Windows Forms app that is distributed via ClickOnce. There is actually very little code in the app. Just enough to load/save data and show messages in the app (multi-threaded).
- Dev.Utility.Processors.dll (Clr C#): This assembly does the heavy lifting for the app. Currently, the app has two features. The first is to seek and destroy temp and cached files created by Visual Studio and SQL Server. The other is to scan your computer for source code and quickly back it up to OneDrive, by default. Much of the processing code for each feature is here which includes sending status update messages to the app.
- Dev.Utility.Common.dll (Clr C#): This assembly has common code used by the other assemblies in the solution. Some of the common code is configuration, the message type used to show information to the user in the app, a type used for queueing and more.
- dotNetTips.Dev.UI.dll (Clr VB.NET): This contains the custom controls and forms used in the app. Some of these include the control used to show messages to the user, header control, performance control, Errors Form and more.
- App.Ads.CloudAccess.dll (.NET Core): If a user clicks on an advertisement in the app (located at the bottom of the app, then this assembly send that information directly to a queue in Azure. This assembly is part of a completely different solution that I will describe next.
Cloud App Solution Example
I learned N-Tier architecture (also called multitiered architecture) a very long time ago and use it for any app/solution I am architecting. I use it in the example above, and this shows how I use it, even for cloud apps. This example shows my cloud app, all hosted in Azure. I’m showing this because it shows what happens to the data sent from the user clicks for ads from the app above.
As you can see, the ad click data is sent to a ServiceBus Queue via the communications layer to the business layer then to the database layer and saved to Cosmos DB. All these assemblies are written in C# using .NET Core. Here are the major responsibilities of each assembly.
- App.Ads.DataAccess.dll: In the database layer, the code in this assembly is just to deal with retrieving and saving data to the database along with any custom methods I write to access the data. That’s it! Think about it like this, the only thing this layer should call is the actual database assemblies, such as the ones for SQL Server, Oracle, Cosmos DB, etc.
- App.Ads.Entities.dll: This is where all the custom data entities used in the database layer should be. You can put others there too. I know someone reading this will say, “Why not just put them in the data access assembly?”. Easy, if you do that, you would have put that assembly on every layer that needs those models, including the client (users) machine. At this point, you have broken N-Tier architecture and will create larger deployments. It could also be a security risk.
- App.Ads.Functions.dll: This is the assembly that contains my Azure Function that is called when the user ad click data hits the ServiceBus Queue and it saves it to Cosmos DB.
- App.Ads.CloudAccess.dll: Currently, this assembly contains the code that sends the user ad click data to the ServiceBus Queue. I plan to add more to this assembly and possibly release it as an open-source project in the future.
- App.Ads.Api.dll: This is the ASP.NET website that is the API (using WebApi) that serves as the communications layer.
- App.Ads.Admin.dll: This is the ASP.NET website that I use to maintain the ad data that is used by the dotNetTips.Utility Dev App. It’s all written using the new Blazor framework that will be released in a few months.
Of course, the assemblies for these two solutions use .NET Framework and Core assemblies along with third-party assemblies (from DevExpress). For more information about this solution, you can read all the articles I have written by going here: http://bit.ly/RealWorldArticles
The Benefits of Reuse
There many benefits of code re-use. I will go over the major ones, to me and why they are important.
Unit testing is very important to validate the code and something I never seen done very much. Most of the projects I work on as a contractor either has no unit tests or very few. Once, while I was at Microsoft, someone from the team that created IntelliTests (does not work in .NET Core) told me that teams should strive for 75% code coverage. I think this is a good goal. It’s very important to do unit testing before sending it over to the quality assurance team. Tell your boss that this is a cost savings!
If you follow what I say in my writing and are practicing good object-oriented programming techniques, then unless a type and its methods are used by another assembly (except for MCV controllers and related types), they should be marked as internal, so they are not exported. This is proper OOP design and can possibly speed up performance. If you do this, then it’s difficult to unit test them. Putting the code in re-usable DLL’s fixes this issue since you will have to make key types and methods public, so they are exported.
There are more ways to test your code and app with integration, end-to-end and visual testing. So, don’t forget that before letting users use your app.
Easier to Maintain
Ever since my beginner programming days, I have seen code copied from one class to another. I still see it today! Once the same block of code is copied this way, then a major maintenance issue is instantly created! If there is a bug in the code or a change needs to be made, then you must do it in 2 or more places. Talk about wasting time and money!
When I worked at Mitchell International here in San Diego, CA you could hear new programmers to the team cursing when a bug fix was rejected by QA! There was so much duplicate code, that when a bug is worked on, there could easily be 4 or more places that it would also have to be fixed! This was one of the reasons I quickly got myself working on new features after I started.
Making re-useable DLL’s can fix this problem. There is a feature in Visual Studio that will show you where all the duplicate code is. Easy! If code like this is found, just put it in a DLL. The way I approach coding now is that most of the code I write, will be re-used, somewhere at some time in the future. So, I just do it right from the beginning, when writing new code.
Easier to Share
If most of the code is in reusable DLLs then it’s easier to share with others on your team, department or another department. It’s then very easy to make NuGet packages to share them too! It’s very easy to do this with .NET Core projects and Visual Studio. These packages then can be shared within your company or even on NuGet.org.
Easier to Update
Coding this way also makes updating the app easier. If a bug is fixed or some other non-breaking change is made, then only that assembly needs to be updated or downloaded. For example, if your boss walks into your office one day (this happened to me) and says that they have decided that company won’t use SQL Server anymore and now must use Oracle, then it’s very easy to make this change.
If architected correctly, most of the rest of the app won’t have to be updated at all! Talk about time and cost savings! In that example, it took me only about a day to change that project to use Oracle, including testing. I didn’t even need to modify the app (ASP.NET) except for the connection string in the config file.
I hope this article will inspire you to think about reuse whenever you sit down and start banging out code. I’ve done it for most of my 25+ years of programming and it’s never let me down. If you get kickback from your boss, remind them that this is a cost and time savings! Maybe not now, but it will be in the future. I guarantee it!
Do have any tips you’d like to share? Please make a comment below.