Partitioning a project into multiple solution - visual-studio-2010

I'm managing a mid-size project in VS2010 (and TFS2010). We have separate teams for different parts, and a team for a "common" part which will provide frameworks and such. Source structure:
Common
+--- CommonLibrary1
+--- CommonLibrary2
+--- etc.
Part1
Part2
etc.
Requirements:
A dev in the "Common" team should use Common.sln that contains only Common code
A dev in the "Part1" team should use part1.sln that contains part1. It references stuff from Common, and should be able to build that stuff (same for part2, etc.)
If a dev in the "Common" team create a new "CommonLibrary3" project, I only want to update Common.sln - I don't want to touch Part1.sln, etc.
TFS build should always build everything
Non-requirement:
TFS-build of just Part1. All of this is a single project, and is always released together.
Separate management of parts.
Sub-optimal solution I know of:
Add Common.sln to part1.sln - seems like VS just copies all project from Common.sln into part1.sln, so projects later addede to Common are not included.
Replace solution files with MSBuild target files - http://sedodream.com/2010/03/19/ReplacingSolutionFilesWithMSBuildFiles.aspx. I guess that would work, but I want the devs to update solutions from VS, not hand-edit MSBuild files.
The TFS Guide books I found calls this a "Partitioned Solution", but doesn't specify how to actually achieve it.
Any recommendations?

In TFS 2010 build definitions you can refer to:
Multiple source control folders to include in your build workspace
Multiple solutions files to build in your build process
So (if I understand your question correctly), regarding TFS team build you have no issues.
The only challenge you have left is that (maybe) on any development system of part1 or part2 developers, that developer should be able to also build the Common.sln. As long as that developer has read access to the common branch, the local workspace can contain both source code bases and both can be build by the developer.
So:
Common developer has RW access to Common, only R access to Part1 or Part2 (to test impact of changes),
Part1 developer has R access to Common, RW access to Part1 and no or R access to Part2,
Part2 developer has R access to Common, no or R access to Part1 and RW access to Part2
This should enable your scenarios.

Related

Can one VSTS project be mapped to different local workspaces?

I have a class library project to be shared by two different solutions in Visual Studio 2017. The solutions are mapped in two different workspaces. I cannot find a way to get the shared project under source control in both solutions. Any suggestions?
I'm assuming that you have two separate Team Projects, each with its own TFVC repository. Underneath one of those Team Projects (say, TPA), you have a common library that you'd like to share with a solution located in Team Project B (TPB).
You can't do what you're asking to do -- even if you could do it, you shouldn't. You don't want to fork the source code and maintain two copies of it. What you want to do is one of the following:
Map a single workspace containing all of the Team Projects and use relative
paths for references. This isn't great, ideally each Team Project is considered a totally separate entity.
Put everything in a single Team Project and maintain a single workspace for everything.
Turn the shared component into a NuGet package and use a Package Management feed. Each consumer of the shared component can then reference a common NuGet package.
I'd say #1 is already excluded as an option. Each Team Project should be an independent entity with nothing shared between it. Since you have things shared, you've chosen the wrong organizational structure. Stop using multiple team projects.
Option 2 is okay, but it's a little bit clunkier.
Option 3 is the preferred, modern way of managing cross-project dependencies. I'd strongly recommend looking into implementing this pattern. If you adopt this pattern, maintaining multiple team projects becomes acceptable again -- you have one Team Project that acts as a publisher of shared components, and another that acts as a consumer. That's sufficiently isolated to consider them independent of one another, and thus an acceptable candidate for multiple Team Projects.
It's worth noting that the modern thought among most experts in this area is that maintaining a single Team Project for all related applications is the correct approach. I've seen teams with hundreds of members and dozens of applications using a single properly organized Team Project with no problems.
While I agree with Daniel on the fact that this is probably a bad idea and that there are alternatives, it's perfectly possible; there's one restriction though: each workspace must have its own copy of the shared project on your hard drive, they can share the remote copy on the server. This si very similar to a distributed source control model and can work just fine.
To make this work, first create one workspace and map the folders locally:
Workspace 1
$/Common/ => c:\src\1stProject\Shared
$/ProjectA/Solution => c:\src\1stProject\SolutionA
Then create a second workspace:
Workspace 2
$/Common/ => c:\src\2ndProject\Shared
$/ProjectB/Solution => c:\src\2ndProject\SolutionB
This way both projects share the same server location and changes made to Shared will directly impact both SolutionA and SolutionB. Locally though, each solution will have its own local pending changes etc.
This solution will work as long as both Team Projects are in the same TFS Project Collection.
The only limitation is that these projects can't be placed in a subfolder of each other, so you can't do this:
Workspace 1
$/Common/ => c:\src\1stProject\SolutionA\Shared
$/ProjectA/Solution => c:\src\1stProject\SolutionA
Nor can both workspaces map to the same local folder:
Workspace 1
$/Common/ => c:\src\Shared
$/ProjectA/Solution => c:\src\1stProject\SolutionA
Workspace 2
$/Common/ => c:\src\Shared
$/ProjectB/Solution => c:\src\1stProject\SolutionB
Alternatives
Nuget
Instead of using shared sources directly, add a NuSpec to the Common project and build & publish the NuGet package to the VSTS package management feed of the VSTS account. Add a NuGet reference to SolutionA and to SolutionB. That way the binaries of Common are shared among SolutionA and SolutionB, but common is maintained independently. This way it's also easier to update SolutionA at a different cadence than SolutionB (this is also the biggest pitfall for this solution).
Git & Submodules/Subtrees
Convert the TFVC repositories to Git repositories. That way you can use Subtree or Submodules to reference Common directly from the SolutionA repository and the SolutionB repository.
MonoRepo/One Project To Rule Them All
Merge all your TFVC repositories into a single TFVC repository, that way both projects can easily live inside the same workspace. Technically this isn't needed to put both projects in the same workspace, but it is easier. It results in a very similar solution as described above:
Workspace Single
$/Project/Shared => c:\src\Shared
$/Project/SolutionA => c:\src\1stProject\SolutionA
$/Project/SolutionB => c:\src\2ndProject\SolutionB
Would result in the same as the following cross-project layout:
Workspace Single
$/CommonProject/ => c:\src\Shared
$/ProjectA/ => c:\src\1stProject\SolutionA
$/ProjectB/ => c:\src\2ndProject\SolutionB
Note
In any cross-project setup, the UI of both Visual Studio and VSTS will fight you. The VSTS team has been working on the ability to make individual Team Projects portable across accounts. In order to do that features like these will need to be dropped at some point. The UI in VSTS build, for example, will not show any other Team Projects in the Source picker. If you type the paths manually they will work (as long as you configure the build to have a Collection Level scope).
Advice
The Nuget solution is the most reliable solution for the type of problem you're trying to solve. The VSTS Package Management feature will allow you to easily share the Common project across multiple projects and even across other VSTS accounts is you want to in the future. It's the most reliable solution.
If you need to be able to edit the files in either solution, I highly recommend you look into Git Subtrees or Git Submodules. Git is the future in any case and these features will allow you to achieve what you need in a much easier to sustain way. They do come with a steep learning curve though.

TFS structure for "base" and "derived" projects

I am looking for some ideas and suggestions on how to implement a class hierarchy type of structure of VS projects in TFS.
Specifically, I want to have a "base" project which will contain all the common functionality the rest of the projects will inherit. When the changes are needed in the "base" project it should be relatively easy to propagate these changes to the rest of the projects which are based on this "base" project.
The obvious approach is to branch other projects from this "base" project and merge up the tree from this root project when there are changes but I've never tried that before and would like to hear from someone who attempted something like this before or has extensive enough experience with TFS to be able to point to inherent issues or pitfalls of such idea...
The projects in source control is actually folders. So your question is somehow the same as how to structure your folders in TFS.
Your base project is the some concept of main in branch which is root folder that acts as a container folder for your main source tree, together with accompanying project artifacts such as design documentation, scripts, and test cases. The Main folder also usually contains your Visual Studio Solution (.sln) files.
In TFS you could convert a folder to a branch.Then you just need to branch your base project to other projects. After have a branching relationship, you will be able to merge changes between the 2 branches. Besides you could also use branches to accomplish the following goals:
Manage concurrent work by multiple teams on the same codebase
Isolate risks that are introduced by different sets of changes to the codebase
Take snapshots and then support subsequent isolated changes (for example, to create a release branch)
Although you can still branch and merge among folders, the best practice for your team is to branch and merge only among branches.
When you perform branch operations, branches have important advantages over folders. Branches support version control features that provide extra visibility into your branch structure and into where your changesets have merged. (For more information, see these wonderful links: Visual Studio TFS Branching Guide)
For inherent issues or pitfalls of such idea, one thing is you might have to resolve conflicts when you get, check in, merge, or unshelve. Another thing is permission. It's better to avoid everyone have permission to merge changes from the “derived” projects back to the "base" project.
Besides you can create multiple teams in the same Team Project and you can nest them to facilitate hierarchy. If you are interested, you could check this blog which shows how to configure that.

How to manage multiple versions of binary dependencies in TFS 2012?

I'm managing release process for couple of projects that target external API. Typical scenario is that a single solution targets a particular version, say v1, of 3rd party runtime in a production and newer version (v2) in development phase. I have to maintain dependencies for v1 for production support but also v2 for a DEV branch. Those scenarios may even go more complex depends on the rollout plan.
I tried branching + nuget but the problem is API I use is huge and it is hard to build a scope of a nuget package. Putting everything into one package makes no sense for smaller projects and on the other hand depending on what features we integrate, combination of DLLs may vary a lot and they are not nicely separated into closed concerns.
On top of it, usually we have multiple solutions that use those APIs.
I was thinking about building API version repository in TFS in some form
- myAPI
|- v1
|- v2
|- v3
Is there a way to configure a build process to look inside a server for referenced DLL files depending on a build setup? I can maintain multiple builds in the system obviously but I don't know how to provide referenced files location for each individual build.

Good Directory Layout for .NET Projects with libraries used across applications and using Mercurial

I've been using Mercurial for a bunch of standalone projects. But now I'm looking at converting a subversion repository to Mercurial thats a lot more busy / complicated.
Given about 40 Library projects and about 20 Applications ( various web / console / wpf, etc) or so. Various apps make use of various Libs. All of this is structured under 1 trunk in subversion. So there's a directory where all the libs live, and a directory where all the apps live. Very easy to find and reference the libs when creating a new Visual Studio Projects.
simplified....
--trunk-|-- libs
|-- apps
Now moving to mercurial, this is less ideal, it seems the way to handle this is with 1 repository for each app? and sub repositories per each lib you want to use?
--app repository-|-- libs
|-- app
Is this right?
If so, when starting a new application in visual studio and you want to add various libs, whats the best/most efficient way to go about it?
I'm getting the feeling the initial setup is a bit painful? As opposed to the subversion layout where effectively you don't really have to do anything other than reference the library in your visual studio project.
So, hence this question, wanting to know a good directory structure, and how to quickly setup a new project using this structure.
Ideally, and this is going to be based on my own opinion and experience in working with larger, distinct applications, but with dependencies, you want to have a repository per distinct, unrelated project, and keep related, possibly dependent projects within the same repo. I'm not a big fan of Subrepositories, but that might just be to lack of exposure.
The reason for this is that you should want to version related projects together as changing one may affect the other. In reality, anything that can be pulled into a single solution and have project references, you definitely want to keep together.
Now, there are some exceptions where you may have a library project that you can't necessarily have as part of a solution, but is a reference for a set of projects. This is where I'd keep a lib folder versioned along side the rest of my applications in the same repo, but the lib folder holds pre-build assemblies. It can also hold 3rd party vendor assemblies as well. This is also important to be versioned along with the project that uses them as you can treat a library update for the main project as a minor release.
For other projects that are truly independent, create another repository for it, as it will have its own version life and you do not want changes to it to affect the graph of changes for your other, completely unrelated projects.
Example layout with several related projects and lib folder:
[-] Big Product Repo
--[-] Big Product 1
----[+] Dal
----[+] Services
----[-] Web
------[+] Controllers
------[+] Models
------[+] Views
--[+] Big Product 2
--[-] lib
----[+] iTextSharp
----[+] nHibernate
Example layout with another unrelated project in it (for sake of argument, a Windows services project):
[-] Small Product Repo
--[-] Windows Services
----[+] Emailer
----[+] Task Runner
In reality, though, your folder structure isn't as important as making sure projects that are being treated as one logical unit (a product) are kept together to ensure control over what is built and released. That is my definition of what a repository should contain and what I use to think about how to split things up if there's more than one versionable product.

What is the best practice for sharing a Visual Studio Project (assembly) among solutions

Suppose I have a project "MyFramework" that has some code, which is used across quite a few solutions. Each solution has its own source control management (SVN).
MyFramework is an internal product and doesn't have a formal release schedule, and same goes for the solutions.
I'd prefer not having to build and copy the DLLs to all 12 projects, i.e. new developers should to be able to just do a svn-checkout, and get to work.
What is the best way to share MyFramework across all these solutions?
Since you mention SVN, you could use externals to "import" the framework project into the working copy of each solution that uses it. This would lead to a layout like this:
C:\Projects
MyFramework
MyFramework.csproj
<MyFramework files>
SolutionA
SolutionA.sln
ProjectA1
<ProjectA1 files>
MyFramework <-- this is a svn:externals definition to "import" MyFramework
MyFramework.csproj
<MyFramework files>
With this solution, you have the source code of MyFramework available in each solution that uses it. The advantage is, that you can change the source code of MyFramework from within each of these solutions (without having to switch to a different project).
BUT: at the same time this is also a huge disadvantage, since it makes it very easy to break MyFramwork for some solutions when modifiying it for another.
For this reason, I have recently dropped that approach and am now treating our framework projects as a completely separate solution/product (with their own release-schedule). All other solutions then include a specific version of the binaries of the framework projects.
This ensures that a change made to the framework libraries does not break any solution that is reusing a library. For each solution, I can now decide when I want to update to a newer version of the framework libraries.
That sounds like a disaster... how do you cope with developers undoing/breaking the work of others...
If I were you, I'd put MyFrameWork in a completely seperate solution. When a developer wants to develop one of the 12 projects, he opens that project solution in one IDE & opens MyFrameWork in a seperate IDE.
If you strong name your MyFramework Assemby & GAC it, and reference it in your other projects, then the "Copying DLLs" won't be an issue.
You just Build MyFrameWork (and a PostBuild event can run GacUtil to put it in the asssembly cache) and then Build your other Project.
The "best way" will depend on your environment. I worked in a TFS-based, continuous integration environment, where the nightly build deployed the binaries to a share. All the dependent projects referred to the share. When this got slow, I built some tools to permit developers to have a local copy of the shared binaries, without changing the project files.
Does work in any of the 12 solutions regularly require changes to the "framework" code?
If so your framework is probably new and just being created, so I'd just include the framework project in all of the solutions. After all, if work dictates that you have to change the framework code, it should be easy to do so.
Since changes in the framework made from one solution will affect all the other solutions, breaks will happen, and you will have to deal with them.
Once you rarely have to change the framework as you work in the solutions (this should be your goal) then I'd include a reference to a framework dll instead, and update the dll in each solution only as needed.
svn:externals will take care of this nicely if you follow a few rules.
First, it's safer if you use relative URIs (starting with a ^ character) for svn:externals definitions and put the projects in the same repository if possible. This way the definitions will remain valid even if the subversion server is moved to a new URL.
Second, make sure you follow the following hint from the SVN book. Use PEG-REVs in your svn:externals definitions to avoid random breakage and unstable tags:
You should seriously consider using
explicit revision numbers in all of
your externals definitions. Doing so
means that you get to decide when to
pull down a different snapshot of
external information, and exactly
which snapshot to pull. Besides
avoiding the surprise of getting
changes to third-party repositories
that you might not have any control
over, using explicit revision numbers
also means that as you backdate your
working copy to a previous revision,
your externals definitions will also
revert to the way they looked in that
previous revision ...
I agree with another poster - that sounds like trouble. But if you can't want to do it the "right way" I can think of two other ways to do it. We used something similar to number 1 below. (for native C++ app)
a script or batch file or other process that is run that does a get and a build of the dependency. (just once) This is built/executed only if there are no changes in the repo. You will need to know what tag/branch/version to get. You can use a bat file as a prebuild step in your project files.
Keep the binaries in the repo (not a good idea). Even in this case the dependent projects have to do a get and have to know about what version to get.
Eventually what we tried to do for our project(s) was mimic how we use and refer to 3rd party libraries.
What you can do is create a release package for the dependency that sets up a path env variable to itself. I would allow multiple versions of it to exist on the machine and then the dependent projects link/reference specific versions.
Something like
$(PROJ_A_ROOT) = c:\mystuff\libraryA
$(PROJ_A_VER_X) = %PROJ_A_ROOT%\VER_X
and then reference the version you want in the dependent solutions either by specific name, or using the version env var.
Not pretty, but it works.
A scalable solution is to do svn-external on the solution directory so that your imported projects appear parallel to your other projects. Reasons for this are given below.
Using a separate sub-directory for "imported" projects, e.g. externals, via svn-external seems like a good idea until you have non-trivial dependencies between projects. For example, suppose project A depends on project on project B, and project B on project C. If you then have a solution S with project A, you'll end up with the following directory structure:
# BAD SOLUTION #
S
+---S.sln
+---A
| \---A.csproj
\---externals
+---B <--- A's dependency
| \---B.csproj
\---externals
\---C <--- B's dependency
\---C.csproj
Using this technique, you may even end up having multiple copies of a single project in your tree. This is clearly not what you want.
Furthermore, if your projects use NuGet dependencies, they normally get loaded within packages top-level directory. This means that NuGet references of projects within externals sub-directory will be broken.
Also, if you use Git in addition to SVN, a recommended way of tracking changes is to have a separate Git repository for each project, and then a separate Git repository for the solution that uses git submodule for the projects within. If a Git submodule is not an immediate sub-directory of the parent module, then Git submodule command will make a clone that is an immediate sub-directory.
Another benefit of having all projects on the same layer is that you can then create a "super-solution", which contains projects from all of your solutions (tracked via Git or svn-external), which in turn allows you to check with a single Solution-rebuild that any change you made to a single project is consistent with all other projects.
# GOOD SOLUTION #
S
+---S.sln
+---A
| \---A.csproj
+---B <--- A's dependency
| \---B.csproj
\---C <--- B's dependency
\---C.csproj

Resources