1

I’m looking for some advice on best practices for Visual Studio workflows.

I maintain several C# libraries which I use in various projects I develop. I also make them available publicly, as packages on NuGet and as source code on GitHub. Because I am often tinkering and tweaking my common libraries as I use them, I typically add the ones I need in a particular solution as external/existing projects. To keep things organized I add them to a solution folder I set up called “external”:

how I currently reference/organize shared libraries

I can then use them in any other project within the solution by simply adding them as a project reference.

To ensure other developers will be able to build my projects from GitHub source code I also include references to their NuGet packages in the projects (i.e., I “double specify” the common libraries, once as a NuGet package and once as an “external” project). VS is smart enough to pick whichever version is more recent, so when I tweak something on my development machine the shared library gets rebuilt as part of the build process:

dual referencing shared libraries

This works well…for me.

But because this all gets published to GitHub it complicates the life of anyone who clones one of my solutions and tries to build it. Since they haven’t duplicated the folder structure of my development machines those “external” projects are undefined and cause builds to fail.

It’s easy enough to simply delete those external projects and the external solution folder. The required libraries will still be incorporated because I include references to their NuGet packages in the projects that use them (note that this requires I update any tweaked common library NuGet packages before I publish the app or library which uses the tweaked library).

I can solve the “missing external projects” problem other developers encounter when cloning my GitHub source code by simply deleting the external references when I push a main/master update to GitHub (and ensure the shared NuGet packages are also updated). But that requires me to remember to do that as part of the publication process...and go through the hassle of re-creating the "external" projects the next time I need to tweak something in the solution.

I could also simply tell other developers, via the README, that they should delete those external project references and the external solution folder. But that seems kludgy.

I’m curious if there’s a better workflow which continues to allow me to tweak/evolve my shared libraries but doesn’t require either me or other developers to jump through hoops to get things to build.

3
  • "Because I am often tinkering and tweaking my common libraries as I use them" Am I correct in understanding that this means that you're trying to avoid the hassle of publishing a nuget package for these tweaks? Would it be correct to say that you're engaging in a form of shotgun programming here (as a variation on shotgun debugging) with regards to your library? How essential is this to your development process?
    – Flater
    Aug 28, 2023 at 1:20
  • "But that requires me to remember to do that as part of the publication process" - can't you write a script for this process?
    – Doc Brown
    Aug 28, 2023 at 13:38
  • Yes, I am doing shotgun programming (love that term :)). Whether I should be doing that or not is a different question :). Aug 28, 2023 at 20:57

1 Answer 1

3

I think you've positioned yourself inbetween two workable scenarios and the hassle you're dealing with now is the result of not sticking to one scenario in particular.

You're using Nuget packages, which are great for versioning and publishing purposes, but this process takes a bit of time and complexity and is generally prohibitive of the kind of shotgun development where you are constantly making tweaks to your library while you are developing its consumer.

From a point of idealism, I would argue that you should not be tweaking your library at that stage. You've introduced a clear separation between the two and you should respect that separation. Your library is a different product from your consuming application, and you're mixing your concerns by trying to develop both at the same time.

Even if you were developing your consuming application and suddenly realized you needed an extra feature (or bugfix) on the library; I would consider this a change of mindset. You've halted the consuming application development, you are now doing some library development, which includes committing, any testing on your part, and publishing of the package; after which you can resume your development on the consuming application.

The main reason for doing so is that I think it's very important that while consumers' needs often lie at the basis of your library's requirements, the actual design and implementation of these requirements should be done in a mindset that does not have a specific consumer in mind. To this end, keeping the separation helps make that distinction clear in the developer's mind.

That being said, maybe this point is idealistic. Alternatively, have you considered a monorepo?

This would enable you to share your library across your services and synchronize commits to both the library and its consuming applications. You could still additionally publish your library as a nuget package for any consumers that are outside of your monorepo, but then they don't get access to the "quick tweak" versions of your library that your monorepo services have access to.

Monorepos also have their drawbacks; but your question does not reveal enough information for me to judge whether these are applicable to you or not. I suggest reading up on the pros and cons of monorepos before jumping in.

I want to point out here that I'm personally not the biggest fan of monorepos but your particular problem is one that they do help ease, assuming that the need to have fast turnaround on shared library code is an essential part of the development process for you.

3
  • This is an excellent answer. Just one comment here: IMO the wording "shotgun development" may sound a little bit too negative. Developing and refactoring libraries together with a consuming application is an excellent way for testing and validating the library functions and their usuabilty. Let me add I can confirm that releasing libs at defined point in time from a "main application" to other clients is definitely a useful strategy. Where I work, we are doing this for years, even before Nuget or the term "monorepo" were invented - this also works with different tooling.
    – Doc Brown
    Aug 28, 2023 at 13:44
  • Thanx, I think you've hit the nail on the head: I was mixing up two more-or-less incompatible things. Aug 28, 2023 at 20:56
  • @DocBrown: I know people are sometimes negative about shotgun debugging but I don't see it as an inherent negative. Shotgun debugging may not be the best default way of working but when you see no other way forward it is the more surefire way to progress to your goal (if slowly).
    – Flater
    Aug 29, 2023 at 1:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.