Solution items/folders are ubiquitous in the Visual Studio world. Open any given VS solution and chances are, you’ll see some floating around. Solution items are files which don’t logically belong inside a project. Solution folders are virtual directories which can be used to impose structure on solution items and projects. Unfortunately, in practice, I find that the two are both more trouble than they’re worth, for these reasons:
- I want to keep my virtual file system congruent with my physical file system but VS provides no means to do this. So keeping them in sync is a manual process which is vulnerable to the following:
- Moving a file between virtual folders but forgetting to move it in your file system and/or source control system, vice-versa.
- Adding a file to a deeply nested solution folder but neglecting to place it in the matching physical folder. The VS default is to add it to the root of your solution, which is almost certainly *not* what you want.
- Adding a file to a physical folder and source control, but neglecting to add it to the corresponding virtual folder. Projects are better at dealing with this, as VS has the capability to show files which exist in a project’s physical folder but aren’t added to the proj. Instant red flag.
- Renaming/moving tends to be slightly irksome in most source control systems. Some (e.g. TFS) require you to explicitly issue a rename command, and others (e.g. Git) can infer a rename in cases where you move a file but don’t edit it. Fortunately, the vast majority of potential rename issues disappear when you have an IDE like VS which has source control integration and simply issues rename/move commands behind your back as you move files around – it knows what you’re trying to do. Exceeeeept in the case where you’re moving files between virtual locations and VS doesn’t even know that you intend to perform a move.
- Because solution folders are virtual, niceties like ‘Open Folder on Disk’ no longer exist. Furthermore, for some reason, solution items annoyingly do not have an ‘Open Containing Folder’ action.
- Anecdotally within our team, we’ve noticed that solution items/folders have the tendency to disappear in source control. A colleague’s theory is that TFS allows you to get latest on a solution without forcing to you save your own pending changes on the sln file, allowing you to acquire the latest version without conflict and then to inadvertently clobber it with your in-memory version when you do finally save. This might be a VS/TFS bug which may or may not have been resolved.
- By definition, solution items are specific to a solution, which is all well and good when you have only one solution. But at work, we achieve code level reuse by branching library type solutions into other solutions. What if I have some solution items/folders in the library solution which I want to surface in all 10 solutions which use the library? Well, I have to manually add them to all 10 solutions which is time-consuming and liable to error – an O(1) operation has turned into a flaky O(n) maintenance task! Project folders/files don’t have this issue.
At work, we’ve decided to avoid the whole shebang as much as possible by:
- Not using solution items. We instead add solution level items to a project called ~ which we create for every solution. VS doesn’t seem to have a project template corresponding to ‘plain container for files’, so I’ve previously created ~ as a C# class library and stripped out the build configuration. I chose tilde as a name because it’s concise and vaguely corresponds to home/root. You could standardise on any convention you want. The only problem I’ve found so far is that ~ has special meaning in PowerShell… consequently, from the parent folder, you cannot cd ~. You must be explicit and cd ./~
- Avoiding solution folders wherever possible. In converting your solution items to project items, most of your s. folders will become p. folders. But some will remain… namely:
- Solution folders which are used to group/structure projects. We decided that these were unnecessary and that project name alone sufficed; e.g. where we previously had Tests\Company.Product.Foo.Tests\ and Tests\Company.Product.Bar.Tests, we flattened the structure and did away with the Tests folder. Obviously, this works better when you don’t have 5000 projects.
- Solution folders corresponding to physical folders which have a pre-defined path; e.g. $(SolutionPath)\.nuget. Not much you can do here.
In short, I don’t think that VS’s implementation of a virtual file system is particularly flawed. I just think that it’s a peculiar design decision to even implement it at all, when what users probably want in the vast majority of cases is a physical folder structure. More peculiar still, is the decision to make it the only option for files/folders which live outside projects.