How to organize a large project with solutions/projects/folders? - visual-studio

We are working on a very large VS project.
We want the project structure to "hint" developers on the logical components and design.
For this purpose, which is best:
One project with many subfolders and namespaces
Split to multiple projects based on logical grouping of classes. Have all projects in the same solution with solution folders.
Same as #2 but have multiple solutions instead of a single with subfolders.

My projects are huge.
We separate each "module" in different assemblies, creating Class Libraries. Something like this:
Client.ProjectName (Solution)
Client (Class Library)
- SectionHandler...
- ComponentModels...
- Utilities...
Client.Web (Class Library)
- Handelrs
- Extenders
Client.Net (Class Library)
- MailQueue
Client.Blog.WebControls.UI (Class Library)
- TopContent.ascx
- PostsList.ascx
Client.News.WebControls.UI (Class Library)
- TopContent.ascx
- PostsList.ascx
Client.Website
Each Class Library is a project under the solution Client.ProjectName or under some other shared solution.
The file system looks like this:
Client
|- Framework
|- Client
|- files...
|- Client.Web
|- files...
|- Client.Net
|- files...
|- SolutionName
|- Client.Blog.WebControls.UI
|- Client.News.WebControls.UI
|- Website
Shared client libs goes immediately under the Client\Framework folder, it is meant to be used on all projects for this client. Specific projects goes under the solution. We also have a folder called Company where we keep projects that can be used in any other project for any client, it is like the company framework.
The solutions we use:
One for the company framework
One for a client framework
One for each client solution
The same project can be referenced in multiple solutions, so you don't necessarily need to create all those solutions.
With this format we could use a lot of things on other projects simply referencing a DLL. Without this structure some projects wouldn't be possible in the given time.

Solutions are just containers for projects, so it's really the splitting of the projects that is in question.
I would recommend using a different project (AKA class library or assembly) for each major functional area. You may still want to use different namespaces within each project, but separating the major functional areas into different assemblies will make each assembly smaller. Therefore, if you need to use only one or two functions in an application, you only reference those two projects instead of the one massive project. This will make for smaller applications that compile faster and have less overhead.
In terms of solutions, you can organize those however you want because like I said, they are only containers. You may want to put them all in one solution...or maybe each in a separate solution...or maybe put related projects into solutions. Personally, I either use one solution, or for large projects, I use a "master" solution so I can easily compile everything in one shot and individual solutions so I can work on projects individually.

A project should be your "atom" of re-use. Or to put it another way, projects are the granularity of reusable code. It's OK to have interdependent projects but each project should be planned to be useful for its own functionality.
A solution is just whatever collection of projects you need for development / build / test. You could have multiple solutions that specify different subsets of projects.
Folders within a project may help but they could be an indication that your project is getting too large.
Solution folders likewise mean your solution is probably getting too large. Can you divide your codebase into multiple solutions, each with a meaningful and testable output artifact? Solutions can depend on (tested) artifacts from other solutions, just as they do on third party libraries etc.
You should also consider how VS and solutions projects map to the granularity of projects on your version control schema and any branch/merge policies you have.

I have grown to prefer a single solution with subfolders for the key domains, and add the projects in those. It's easy to browse, and gives a rough idea to your devs as to what goes where.
Having multiple solutions is mostly useful if the integrations between the components in eigther solution is loose, so each team has its work solution, and tests against released components from the other teams' solution.

Related

Hierarchy of vendors

My go project consists of many components. Every component has its own vendor directory, which is populated by the dep. Because components have similar dependencies, there is a huge duplication in vendor directories.
Additionally, vendors are quite big: ~20MB.
My idea is to reduce the size of the repository by defining common vendor, on the top of the project.
project
vendor
|--component1
|----main.go
|----vendor
|--component2
|----main.go
|----vendor
Every component needs to define only dependencies specific to him.
To not provision common dependencies on every dep ensure executed on the component level, we can specify which packages should be ignored in Gopkg.toml file:
ignored = ["github.com/aszecowka/calc"]
Question: Does anyone use this approach? Any alternatives?
Update Context:
In my company we are investigating monorepo approach, we try to consolidate different go projects, but we end up with a really huge repository - mostly because of many vendors directories

Separate project for core modules IntelliJ

If you are using a module in multiple projects in IntelliJ IDEA is it common practice to make a new project for these modules or to make the modules in one of the projects they are included in?
It depends on how you're working, whether the common module is developed by you or another team, and other factors. Often, common code is put in a module which produces a jar that the other modules depend upon, and include them all in the same project. This is normal when you're developing the common-code module at the same time as the project and changes are typically committed together (although not necessarily to the same repository or branch). If multiple projects use the common-code module though, and it's developed as a separate library, then it should maybe have a project of its own.
Also, you should probably be using maven when things get this complicated.

How to do dependency management in Visual Studio/MSBuild

There have been many posts on this topic, but I have yet to find the "real" solution.
How does one manage their dependency tree (both compile time and runtime) using MSBuild project files (i.e. Visual Studio project files via project and file references)?
It is well known that project references from child projects will not be copied to an application bin directory if there is no compile time reference, even if there is a runtime dependency, and even if copy-local=true. Hence, any loosely coupled component will not be copied over.
The hack to solve this problem is to include the dependency in the parent project with copy-local=true. However, this basically destroys your dependency tree as you no longer know where the dependency is and ultimately, as your app grows and morphs, you end up with a version of DLL hell. Your parent project ends up with 10s to 100s of dlls, most of which are runtime dependencies of dlls in child projects.
Another hack is to write a custom targets file and call it from every project file: http://blog.alexyakunin.com/2009/09/making-msbuild-visual-studio-to.html. But surely there is a better option. This is such a bread and butter thing. Java devs never have to deal with such trivial issues.
From what I can gather, the Microsoft way to solve this problem is to register every dependency in the GAC for every dev, test and production machine. But this is stupid and annoying. I won't bother giving this option and educated rebuttal.
Avoiding the GAC option, how could one use MSBuild to manage a dependency tree that includes runtime only dependencies? How does Microsoft do it? Surely they don't run custom targets files like the one in the link above.
I hope someone from an enterprise .NET background can step up and offer some real advice on this. Otherwise I'm just going to have to rewrite all my build scripts in NAnt (shudder).
Thanks All.
UPDATE
In response to some comments, the following is a practical example of the issue from my current project.
The app is a Web Application project that exposes a suite of WCF services. It has an external domain DLL containing the external service classes and an internal domain DLL containing internal service POCOs, domain objects and DAOs. There is a separate integration DLL containing interfaces (DTOs) for all the internal domain classes that allows us to completely decouple the external and internal domains. The whole thing is wired up with Spring.net. I hope this is clear, let me know if you need more clarification.
My current build process is to use MSBuild to generate a deployment package for the web application (in TFS Build). So while the whole solution is built initially, only the output from the web application gets packaged. Therefore, the Web Application is treated as the dependency root and I expect that any loosely coupled child references should get copied over on build if they are set to 'copy-always=true'.
So the Web Application contains a reference to the external domain DLL which contains a reference to the internal domain DLL which contains many references to 3rd party libraries and various indirect and loosely coupled dependencies required by the 3rd party libraries.
The problem occurs when there is a 3rd party dependency in the internal domain DLL e.g. oracle.dataaccess which is required by NHibernate at runtime. Even when I set 'copy-always=true' on these DLLs, they do not get copied to the Web App package. The only way I can include them in the package is to add these DLLs to the Web App's references. I don't want to do this because I no longer have a meaningful dependency tree.
I hope this makes the issue clearer. Please let me know if anything is unclear. It's hard to describe this sort of stuff.
If anyone is also having a similar issue, please speak up and share your experience.
I really want to give you a better answer but unfortunately you didn't put enough information about your solution/projects and your dependencies, so I will try to give you several ideas and I hope one of them works.
The easiest thing to do as you said is to set up a separate folder with all of your dependencies and create target file that will copy them to your bin folder. If you have dependencies that are not changing frequently that might work. If another team from your company is building them and they change frequently, this approach is not good.
Another simple approach - if you're referencing your dependencies from your solution only you can change the build path, so that they build directly into the bin folder of your main project. This way you don't have to reference them directly.
Use NuGet. You have a separate team producing loosely coupled dependencies it may make a sense to set up local NuGet repository and use it for that http://juristr.com/blog/2012/04/using-nuget-to-distribute-our-company/
I hope that helps.

Deploy solution which includes external projects

My project have the references to the bunch of projects from another solution (this solution also linked to own Git repository), but for convinience (to be able debug and modify them from one solution) I include these projects to my web-project solution which I want to deploy on AppHarbor. Maybe it could be said that these are sub-modules of my solution. But now I can't figure out proper way to deploy the solution on AppHarbor.
More structured description:
--Solution
------DeployedProject
------[SolutionFolderForExternalProjects]
---------Proj1ReferencedFromDeployedProject
----------Proj2ReferencedFromDeployedProject
Solution - linked to repo1
Proj1 and Proj2 - also belong external solution which linked to repo2, still ADDED to the repo1 explecitly -
git add SolutionFolderForExternalProjects/
How I should handle this sort of deployment?
AppHarbor really needs all dependencies pushed for us to successfully build you project. Generally, having one solution reference projects in some other random location on your local drive and checked into a different repository is probably not an optimal model. It's also bound to cause problems if some other person has to check out and build your code.
You should consider either combining the two solution structures into one repository (you can still have multiple solution files, see the AppHarbor solution file convention). Alternatively, package the respective dependencies up as NuGet packages and include them in your project using NuGet.

Project Naming Convention

I am in a debate about what a best practice would be for naming projects within a .sln on our team. We are working in Visual Studio and debating about what the project naming and placement of classes should be. Here are the two arguments:
There should be a "Common" project which will contain two folders: "Contracts" and "Model". Within "Contracts" folder will be the interfaces and of course within "Model" folder will be the data model. The advantage to this is that there will only be one .dll published which will have both the model and contracts within it.
There should be a "Model" project and a "Contracts" project. "Model" project should contain the data model and the "Contracts" project will contain the interfaces. The advantage here is in the naming, you know what will be in each .dll.
So simplified the question really is, is it better to have two separate projects or one project for the interfaces and model?
I'd separate them into separate projects. Your solution will likely include more DLLs, and you'll want to be able to access the interfaces from any of them. If you dump them into the same DLL with your Models, you run a higher risk of a circular dependency down the road.
It depends, I would keep projects on RE USABILITY basis. Means each project specific to content oriented.
Also note even after keeping separate you can merge them in single dll. So you objective of naming will also be achieved.

Resources