I've got a question about references between projects in a solution. Most of my previous applications have just had one or two projects in the Solution, but this time I want to divide the application further.
I'm starting a new Solution in Visual Studio 2008 now, and have created several underlying projects to divide the separate parts of my application.
But currently I'm just creating the different projects on a whim, and creating references between them when I need to. Sometimes I end up in a situation where two projects need to reference eachother, but that is not allowed since it would cause a circular dependency.
Are there any rules/tips/patterns I should keep in mind when I create the different projects, and linking them together?
Should I start from the inside, and go out? Having the "core" projects refrence all the outerlying projects, or perhaps go from the outside and in where the independent projects all reference the "core"? Or the third option where I have business in two projects, and they both reference a third project?
Indeed you can't have circular references, but to be honest what would be the benefit of splitting the solution into small project if you had interdependencies between all of them?
Usually before I even open Visual Studio I take a piece of paper and split my problem into logical functional areas. You can draw a Utilities assembly at the top and all the GUI's, web services and other end projects at the bottom. The Utilities project is not going to reference any other project, and the ones at the bottom will not be referenced by anything. Then you think what functionality is common for these, e.g. all GUI's can share a common UI project with common user controls and dialogs, and this UI project will reference the "object model" project, etc. The project at the bottom can only reference what is above them.
Often when it appears that you need a circular reference, you can nicely get round it by defining an interface in the lower level assembly, and providing implementation in the upper level.
Without knowing what are you exactly doing I am afraid that's the only advice I can give you.
It's a bit old-fashioned, but for help in deciding how to split into projects, you could look up "Coupling" and "Cohesion" in wikipedia.
Also, while we sometimes think of these decisions as "style" rather than "substance", we should remember that assembly boundaries do have meaning, both to the compiler and to the runtime. A couple of examples of that...
The C# compiler understands a keyword called "internal". To make the best decisions about factoring into separate projects, you should really understand the power of this.
The JIT compiler in the runtime will never inline a function call that crosses an assembly boundary, which has a performance implication. (The reason is to do with Code Access Security).
There are many more examples, so the decision really does make a difference.
I'll use a Winforms applications as an example. The pattern I have started getting into is this. The solution is called Example.
Example.Entities - This project will contain my business objects and the related heirachy of classes
Example.Dal - I put all business logic and data access logic in this project (namespace) This is the code that loads your business objects and then passes them to another layer.
Example.Gui - I put all my Winforms and GUI utility code here and my 'main' starting entry method. You could also just choose to call this project Example. I still like using the namespace Example.Gui for code separation.
Example.Test - You can put all your test code in this project.
I try to drive code into the Entities if it belongs to one of the business objects or a business object collection.
Gui will reference the Entities and the Dal (Data Access Layer).
Depending on how you write your Dal it may reference your Entities.
Test should reference Entities, Dal, and maybe Gui.
The Entities is its own Assembly dll so that you could use it in other projects. Or return them from a .NET SOAP Service.
The GUI layer should view the internals of the DAL as a blackbox. Your main app should not care how the business objects get loaded or persisted. But you should use your Test project to test your DAL thoroughly.
Related
i joined a new project where they use c#.
I noticed that several dll's were being add in the references
From my knowledge and the e-learning that i have done, after building a class(which has some Methods & data), a DLL is generated.
Now in a new project, the class that just got converted into a DLL is added as a reference so that the functions defined in it could be called.
So, now my question is:
1) what is the need for converting the class file into a DLL file. Even it were a Class file, I could still be calling the functions defined in it by adding its namespace at the top of the code
2) If After adding the reference of the DLL , I deleted the entire contents of the project, leaving only the dll untouched(and in the same place), would the class using this dll still work
Separating your code into different projects (each of which will create a separate assembly) has various benefits:
It makes the structure of your code clear. For example, it can separate your storage layer from your business logic, and also from your user interface.
It allows reuse: two different user interfaces can refer to the same assembly containing the business logic, for example.
It allows greater encapsulation: classes which are only needed within their own assemblies can be declared as internal (which is the default for top-level classes in C# anyway) which means code in other assemblies won't even know about them. If all your code is in a single assembly, all those classes will "know about" each other.
Now choosing just how many projects to have is a balancing act - I've certainly seen applications where this has gone much too far, with lots of assemblies containing just a single class. If you have a large number of assemblies, that becomes a headache in terms of project and reference management. However, having too few assemblies makes it harder to reuse that code cleanly.
In addition to Jon Skeets answer, I'd like to add "updateability" as well. For me, this has two benefits
one is that the build time becomes smaller if only one project needs to be rebuilt
and second, pushing to "release" could be limited to a few dlls instead of one major .exe.
The first might not be a big deal in C# since projects build pretty fast, but for instance switching to C++ would be a big impact, since C++ code take a long time to compile.
The benefit of Separating is that it lets you change the internal implementation without breaking client code. It doesn't protect you if you decide that you need to change the interface to your code, but that's a different matter.
they can reuse their code. but if they use classes every time they need to implement these classes ( in the best way copy and paste all codes )
when they use dlls in instead of classes they can update all project easily by just Update one or more dll although if you use class in multiple projects you suould modify all classes in all projects.
I might add that a class is a language construct while an assembly is a deployment package.
Already in UML those are two totally different things.
http://en.wikipedia.org/wiki/Package_(UML)
When approaching the new idea of subdividing a solution, projects may be seen as "places" in which to put namespaces (i.e. folders) and classes (i.e. files).
It will take some time until you realize that a project best fits the concept of stratum (or layer) which is an architectural separation of a system.
When stratifying a system, you'll realize that the most crucial problem to tackle are the dependencies between strata (which would be the references to projects or dlls).
There cannot be loops but more important, you should study OCP (Open-Closed principle) and ISP (Interface Segregation Principle) and DIP (Dependency Inversion Principle) of SOLID:
http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
At that point a new question will emerge. How can you know which classes depend on each other or do not? You may draw class diagrams, but there is a conceptual approach to the problem. Over the years it becomes a "practice" of designing systems. The concepts are described for educational purposes in GRASP:
http://en.wikipedia.org/wiki/GRASP_(object-oriented_design)
The most important parts of GRASP for stratification are "Low Coupling" and "High Cohesion". In other words, you should batch functionally very similar classes in a stratum and separate through the stratification classes that functionally are not very much related to each other.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Namespace/solution structure
If I am creating a large C# app, should I keep it all in one project?
I plan on having a data layer and GUI layer. Should these be in one project or should they be split up into two projects? At this stage I think it should all be in one project, because you can just have a separate folder of classes that represent the data layer and instantiate them when needed.
Let's say I had a separate project for the data layer, what should this project (and therefore the DLL) be called? I am not going to call it <ProductName>_DataLayer.DLL. You never see that.
Are there any other important issues? Is it important to keep the size of the main .EXE down?
My personal favorites on the topic: Scott Hanselman, Mike Roberts
You should make these layers as separated projects inside the same solution for example the data layer would be a Class Library project and it might be named YourProjectName.DAL for example ProductName.DAL.DLL or DataLayer
Data and GUI separation is always recommended, you never know what you'll need to do with the data layer in future.
I'm using the .Data .UI naming conventions, and it's fine.
I would definitely keep separate layers in their own projects. Depending on the size of the application, I would also recommend looking at breaking it down further into logical groupings based on functionality.
You can call it whatever you want. You can set the assembly name to be different than the project name in the Properties window of the project.
The consideration you have to make is whether you want to reuse the datalayer between multiple projects. If the answer is yes then you should put it in a separate project.
If no, it might still be wise to separate it from the GUI simply just in case a scenario comes up you didn't think of. (e.g. you decide to create a webservice)
Naming:
I prefer DATA and UI for naming conventions.
If the solution becomes really big, you can consider using 'solution folders'.
The more simpler way is to have all projects in the same solution.
But if you have a lot of project - the projects which were created a long time ago and are not modified (or modification is vary rare) - is better to exclude them from solution, move DLL's to some common folder and use as dll references from the solution.
For name we're using dot separated - for example <project>.dal.dll
Different projects within the same solution is a good way to do it, but really depends on how the project will be used.
At one point it was common to have a ProjectName.UI > ProjectName.BLL > ProjectName.DAL architecture, then create a Model project to define data contracts to move data between the layers.
BLL = Business Logic Layer
DAL = Data Access Layer
Each layer is compiled into different assemblies, with an EXE for your interface. The size of your compiled EXE isn't really a concern, but more getting the architecture right - if you have a separate project for each layer it will make your deployment more manageable.
Now it is more common to use the Repository pattern architecture, which lends itself well to using ORMs. It you want testable, component based code that is easy to develop and refactor you should definitely look into using repositories.
I am working on a project in which my entire team is facing the following problem, please help me to discover the issues associated with the approach which we have decided to follow so that we can save ourselves beforehand :)
We have decided to separate out the entire code of our application into just three projects in a single solution.
1) One project will contain entire UI
2) Second will contain entire business logic. In this project the code corresponding to different modules of our application will be separated via different namespaces rahter than having separate project for each modules or dependent modules.
3) The third project will contain all the common code
I am still able to see that there might be some problem in future if we put the entire code in second project under different namespaces in a single dll rather that splitting it in different dlls/projects.
We are working on a WPF based application.
Please help!
Shahil Gautam
I am still able to see that there might be some problem in future if we put the entire code in second project under different namespaces in a single dll rather that splitting it in different dlls/projects. We are working on a WPF based application.
The only "problem" with doing this is that it's a bit easier to "accidentally" reference types in other namespaces. If you separate into separate projects, the only way to "pollute" your type with business logic unrelated to it would be to explicitly add a reference. When it's in the same project, you can have a using statement or a fully qualified type name, and "use" an unrelated type without any compiler warnings.
I think that's a sensible choice. I general, assemblies should be units of deployment. There is no need to have 10 assemblies if they are always going to be deployed together.
One issue however is that you will have to be more careful about your dependencies within a project. When separating things into different projects, there are physical barriers for introducing inappropriate dependencies, while now you will have to be more conscious about this. A tool like ndepend might help you find suspicious dependencies in your code.
I do not see why you would want to have multiple namespaces within your business logic project.
There are two possibilities:
ONE. All of the types that you define in the project have different unqualified names.
In this case, separating the namespaces would have little purpose. The only benifit would be that the intellisense object selections would be shorter and clearer when the usings to the other namespaces are omitted. Putting the types into separate projects would accomplish the same thing just as well, and offer better separation of concerns.
TWO. Some of the types in the different namespaces have the same unqualified names.
In this case, confusion could easily result, whenever a using from another namespace is added in an unsuccessful attempt to reference a type from another namespace with its unqualified name. If there is no danger of that happening, then, once again, why not put the objects into separate projects, since, clearly, the lines between the domains are sharply drawn?
I always run into a problem where my projects in Visual Studio (2008) become huge monstrosities and everything is generally thrown into a Web Application project. I know from checking out some open source stuff that they tend to have multiple projects within a solution, each with their own responsibilities.
Does anyone have any advice for how to refactor this out? What should be in a separate project vs. part of the web project? Can you point me to any reference materials on the subject, or is it just something you become accustomed to with time?
Organize your project cleanly into namespaces. Namespaces should not be too big, not too small. Make each namespace have a public "interface" (i.e. a set of public classes) and don't access internal implementation details of the namespace from other namespaces. Different namespaces usually address different parts of an application, e.g. you'll have namespaces related to UI, business logic, helper functionality, etc. The Framework Design Guidelines have some good suggestions how to design namespaces.
When you feel that your project grows too large, simply identify sets of namespaces that are clearly related to each other and move them to separate projects. Since other namespaces already just use the public interface of the moved namespaces, refactoring the namespaces into new projects is merely a file-move-operation.
Start from the bottom up (your simplest classes that don't depend on anything else besides the Framework) and see if you can isolate the dependencies into functional units. For instance, if you have a bunch of data or business logic classes that reference each other, but never reference any of your UI classes, then you have a candidate for splitting off into another project. If you can't find clear separation points, then you have a design problem and should probably do some refactoring.
I also agree that using namespaces is a good place to start. Even within a project, you can often isolate or minimize dependencies in a way that naturally groups classes together. Putting them in the same folder reinforces this grouping as a functional unit and may really help the poor guy who has to maintain your code in the future. Trust me, I try to think about that poor guy because, on more than one occasion, that poor guy has been me. Twas a small comfort that the person who wrote the code had the same name as me at the time that he wrote it.
Check out the guidance given by the Sharp Architecture project. Its ASP.Net MVC but the same principles apply to ASP.NET and other projects. The guys that put this stuff together are smart I generally use their advice as the default and only stray when I have a good reason.
The basic tiering that they propose is
A core project for your domain objects and interfaces for accessing external services (including persistence).
A data project that depends on core and implements all the interfaces for accessing persistence
An application services project for supporting application-level concerns such as logging or login validation. This only references core.
A web project that holds only views.
A controllers project that holds your bootstrapping code and the code for coordinating your web layer, domain.
In the case of an asp.net app I like to use the mvp pattern which would basically mean the
Web project holds your WebForms and codebehinds which should contain only the minimum amount of code required to redirect to the presenter. You probably also will need to put your bootstrapping code in there. This is due to an ASP.Net limitation and you should NOT reference any of that stuff from your codebehinds.
Controllers project is replaced by a presenters project. The big difference here is that somehow the presenter has to be instantiated by the WebForm rather than the other way around.
You can also try to check out the ASP.NET MVP project.
How should I divide source files into projects (within one solution) to
be able to use common classes in more relatively independent apps,
avoid lots of dlls needed (preferably all in one file for each application),
keep it fast?
There are working (data processing) classes, User controls, some utility classes and Forms of the application.
You can make a separate assembly by creating a class library, and use that library within other projects within your solution. Just put your reusable classes within a class library project, and add a project reference in your applications to that library.
Each time you separate out code into a separate (reusable) assembly, it does add one extra DLL (the class library project) as a requirement at runtime, but this is very minimal.
There are no real (significant) changes to performance when doing this. It is a very common practice.
You should make Class Library project(s) for each logical unit of classes, then add references to the libraries in each project that uses them.
For example, you could have a Common library that contains basic classes used by everything else, and perhaps a Controls library that contains user controls.
Each logical unit of classes can go in a namespace within the same library or in a separate library; you need to decide which.
It would be a good idea to drop the second requirement of avoiding lots of DLL's. If you put your common code into a single "common" DLL then you need to recompile every time any class is added or modified. This could then give you a terrible versioning problem that is worse than managing lots of DLL's.
You should group your common code, by the functionality they provide, into separate DLL's. So one for data access, one for user controls, one for each type of utility function, etc. Then if you have web service that accesses data you won't need to recompile the service when you add a new user control to a single DLL. Only those apps that depend on the change will need to be recompiled.
You could put the common classes into one assembly (say CommonUtils) and then use namespaces inside for the groupings to indicate how they are split