With our Proof of Concept demo with the customer completed, we are now ready to move on to the real solution.
Lets talk about source control. If you don’t have a favorite, find one. My preference right now is SVN. However use what you feel comfortable with. Make sure you understand it though. Source Control is your lifeblood. If you haven’t spent any time in the docs, or searching the web for best practices for your source control, do it, now! A good place to start, is Eric Sink’s Source Control HOWTO.
Now on to the “Solution”. It kills me that this gets overlooked so often. We are in a rush to get started, so open up VS, create project, and jump into writing code. We were supposed to get rid of those urges in our Proof of Concept…
The solution truly is your first public deliverable. If you work on a team, its the first thing the other developers will see. And your teammates are going to be the hardest group to appease.
Things to think about when setting up your solution.
- Expect Change – I typically end up reworking my solution layout 1-3 times a year. Planning for change up front puts you in a position to allow you to try out new ideas midstream.
- Don’t go overboard – a solution with 10 projects will typically always build faster than one with 40. Separating out each individual component into its own project may not be the best idea.
- Avoid too much depth – We all want to be fast, the solution should be in a layout that walks me to what I need to work on quickly.
- Avoid “Common” projects – Common projects turn into trash dumps that everything lands in. In my case I have a “Core”, core is a common project but it has rules. It can’t be dependent on any other project. This puts a restriction on what can be put into it.
- Refactor happens, in both directions. Leave space in a “Core” library so you can move items up the hierarchy so they are usable across many sub-systems. I try not to put things into my core library initially. Some things are easier to develop on a micro-scale in the library that utilizes them. After the bugs are worked out refactor them into the Core.
- Keep references local. You should never have any references or build steps that expect a full path (aka c:\windows\Microsoft.Net). Copy those referenced assemblies to an Externals directory tree, and check that into source control.
- Solution layout should match the file system as closely as possible. Really the only reason it shouldn’t match is that you are trying out some layout tweaks to see how they feel before you go through the process of relocating files on the file system.
You can find a sample of my current layout at
coderjoe.codeplex.com –>Source Code->Browse-> trunk/Samples/SolutionOrganization
The top level is split out into zones.
- AssemblyInfo - common items shared across all projects. I typically put a constants file in here with all internal classes for my true constants.
- Core – This is my bottom layer refactor point. This is framework level code. Custom Linq extension methods, wrappers around streams and other utility classes or mini-systems like lightweight dependency injection systems.
- Data – These are my Data layer classes. One project for each database. Ideally these would contain mostly generated code using some other persistence framework.
- Databases – If you choose to store your your database schema scripts alongside you project, I’d put them here. Again 1 project per database.
- Externals – This is where I put all of my external references, my SharpZipLib assembly, the projects I download from codeplex or sourceforge. Anything that I didn’t produce as part of this project and expect to be mostly maintained outside of my project. Try to keep this structure and code as close to original as possible, makes it easier to manage merging in bug fixes to the projects as they change.
- Services – I typically like to wrap my database, and business logic together into a service of some sort. Now this doesn’t have to be WCF, or a WebService. Could just be an SOA style class. Based on n~tier design, you can consider this the Business Layer.
- Utilities, Websites, Applications – These are all of my final outputs. I don’t really have a pattern for this area yet. Utilities are typically console apps, so a listing of single projects is in the folder. Websites are very similiar to Utilities. Applications, meaning WinForms or WPF, typically have supporting libraries to go with them. so maybe 1 more level of subfolder below Applications with the Application name. I’m game for ideas here…
Now, at the low level, I’m sure you noticed the Globalization and Configuration projects. These 2 projects sit below Core in the project dependency hierarchy. I put this down at this level to serve as a gathering spot. I’ve worked on too many projects that developers get frustrated with these 2 items. They are either spread over the entire solution in little silo’s, or just flat never thought of. Either state is unusable, and therefore un-maintainable.
So when you get tagged with the need to localize your app, pass along the Globalization assembly to your localization team and be done with it. Or the more likely case of needing to tweak a setting on production, just pop open the config, add the setting and we are done. A little bit of forethought can go a long way to keeping things maintainable.