Sherlock
Sherlock

Reputation: 5627

Structure of a Medium-Large scale project

I'm a beginner programmer, apologies for any stupidity.

Having come from a python background creating small projects with only a few classes, I would have all of my code in one file most of the time.

I've been learning c# recently, and I'm writing a reasonably large console application (10,000 lines +). I obviously can't put everything in one file here, but I'm not sure how I would go about separating the project into smaller segments.

The way I have done this so far, is to create a new project for each namespace within my solution, and split each class into a separate file accordingly. So far, I have around four namespaces. I have written each namespace independently, with a view to use each one going forward in other projects.

I'm at the stage now where I would like to piece together each namespace to build my console application. How do I go about doing this ?

Also, am I structuring my code in the right way ?

Also + 1, is it possible to use files located in a completely different directory within a project ?

Many thanks in advance.

Upvotes: 2

Views: 3407

Answers (4)

moribvndvs
moribvndvs

Reputation: 42497

When you start with a namespace, you'll usually use your company or organization name (say, "A"). If you have multiple products/projects and are creating code for that item, you'll want to add a qualifier (say "B", "C", etc., so you'll have A.B, A.C, etc.).

Then general approach is that you want to group types together in a namespace that are related. If you create a type and it is general purpose/utility/one-off solution to a common problem, you'll want to keep it in a broader scoped namespace. When you find you are creating a number of types to support some feature or purpose, you may wish to create a narrow namespace to contain those types. For example, let's say you need to write several data access components for A.B, which contains data transfer objects, data access objects, etc. You may wish, then, to put those types in something like A.B.DataAccess.

However, remember that .NET uses an OOP paradigm. One OOP paradigm is code reuse. So if you access data in both A.B and A.C, you'll do well to create reusable data access components to encourage code reuse in both projects. In that case, you may wish to have a project such as A.Common, which contains common types used by any of your products, that contain general use, generic, or abstract concepts that can be utilized in A.B, A.C, etc.

Let me try and go further with that example.

  • Project: A.Common (name of assembly)
  • Purpose: Reusable types for any project
  • Namespaces: A, A.DataAccess
  • Types: A.DataAccess.DataAccessObjectBase

  • Project: A.B (name of assembly)
  • Purpose: Types for product "B"
  • References: A.Commmon
  • Namespaces: A, A.B, A.B.DataAccess
  • Types: A.B.DataAccess.DataAccessObject (implements A.DataAccess.DataAccessObjectBase)

  • Project: A.C (name of assembly)
  • Purpose: Types for product "C"
  • References: A.Common
  • Namespaces: A, A.C, A.C.DataAccess
  • Types: A.C.DataAccess.DataAccessObject (implements A.DataAccess.DataAccessObjectBase)

That's a pretty simplistic and crude example, but hopefully it will help you visualize the relationship between assemblies and namespaces.

Some other tips:

  • Don't go overboard with creating namespaces, especially when creating deep namespaces (such as A.B.Something.SomeMoreStuff.EvenMoreStuff), unless it sensible. It makes it a little harder for you to find things.
  • Namespaces should go from broader purpose to narrower purpose. Furthermore, if you create a type in a narrower namespace that relies heavily on stuff from a broader namespace, be sure to place it under the broader namespace. e.g. A.B.Broader.Narrower.

Finally, you should continue to create only one type per source file.

Upvotes: 3

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236328

Namespaces help you to organize your code and provide separation of concerns. It could be done also by creating folders or separate projects. With good logic separation you can build maintainable and scalable applications.

When you taking decisions whether to create new folder, or new project you should rely on common sense. For example, creating several projects for hello world application is an overkill. Creating folder for single class is overkill too. But when you have several classes closely related to each other, consider to separate this particular concern from other application. E.g. if you have CustomerRepository, then you add OrderRepository and VendorRepository. Its good decision to highlight concern, which they are represent. Create Repositories folder and move all those classes there.

With large applications its common to separate such concerns as business logic, data access logic, and user interface. Usually classes which relate to these concerns go to separate projects. Keep in mind, that separation done to make your code easier to understand and maintain. So, namespaces should describe concerns to you and to anyone who will maintain your application. E.g. you can use three projects:

FooCompany.BLL
FooCOmpany.DAL
FooCOmpany.UI

Thats acronyms of Business Logic Layer, Data Access Layer and User Interface. There is no 'standard' names. You can use anything which will describe your code better. Here is example of project structure I usually use for company Foo product Bar:

// Assembly for business logic
Foo.Bar.Domain
Foo.Bar.Domain.Model
Foo.Bar.Domain.Services
Foo.Bar.Domain.Repositories
// Assembly for data access
Foo.Bar.Persistence.NHibernate 
// Assembly for application services
Foo.Bar.Services
// Project for presentation    
Foo.Bar.Presentation.Web
Foo.Bar.Presentation.Web.Controllers
Foo.Bar.Presentation.Web.Views

Btw common practice to start namespace name with name of company you are developing for. SeeNamespace Naming Guidelines. That allows to avoid names conflicts when you have two classes with same name in different namespaces.

Upvotes: 2

Chris Sinclair
Chris Sinclair

Reputation: 23218

Sounds more or less on the right track. Addressing your questions/structure:

1) Don't need to have each unique namespace be represented by its own project; you can (and likely should) have multiple sub-namespaces within the same project if it helps organize your classes. In your case, it sounds like each one is being programmed as its own stand-alone component, so a project for each one makes sense.

2) Your splitting each class into a separate file is good, keep doing that.

3) Not sure about what you're asking about piecing your code together. Do you mean how to go about physically referencing/linking the projects in Visual Studio or best practices to code/access your API? If the former, you can right-click the "References" item under the project and point to the project (not its compiled DLL). If the latter, there are a variety of programming patterns you can follow, but generally you'll want to abstract a nice API out of the projects so you aren't concerned by the inner-workings of your code.

4) You can definitely reference files from a completely different directory. Just right-click on the project or folder, choose "Add -> Existing Item" then browse to the file. You'll probably want to add it as a "link" so it doesn't physically copy the file: http://msdn.microsoft.com/en-us/library/9f4t9t92%28VS.80%29.aspx

Here's another StackOverflow question that goes a bit into possible solution structures: Solution: Per application, or per application suite

Upvotes: 3

Likurg
Likurg

Reputation: 2760

I'll begin from last question to first. You can use files located in a completely different directory within a project. I think you go in the right way. About different namespace you can use this code

using System;
using namespace1; 
using namespace2;

Upvotes: 1

Related Questions