This post is a continuation of my ongoing Enterprise Extension Development blog series talking about how to effectively leverage DotNetNuke in complex environments. In Part One we set the stage for why it is important to look at Enterprise Development slightly differently. In part two we started on the slight differences to basic project structures needed to ensure that we can "Compile Anywhere" and move our projects quickly between machines etc. In this part of the series we will take a look at your code structures within, to handle interdependencies etc successfully.
Template Default Structures/Recommendations
If you have started with the basic templates as we outlined in the previous postings you will see a project structure for your module that might look similar to the following. Specifically looking at FOLDERS.
- ModuleName
- App_LocalResources
- Components
- SqlDataProviderFiles
Your project may be slightly more detailed than the above, however, the general comments on this structure will still apply. You can see from here that you have a fairly detailed project structure. Your App_LocalResources folder for all localization files, your components folder for all of your classes, and then a SqlDataProviders folder that is there for all of your SQL Setup scripts. This project structure works great for one-off modules. But how does this expand to an enterprise situation? How do we build modules that can leverage code that might need to be shared? How can we be assured that eventually we will not create a circular reference between modules as our projects grow in complexity? This is the next question to address.
Possible Solutions
Looking at the structure issue identified above there are many potential solutions. Each of these decisions have their own merits, and depending on the situation the truly correct answer might vary. In this posting I'll detail my preferred solution, I've found that it works for most situations, but your milage may vary.
To help set the stage for a project structures lets consider a situation where we have a solution that we know has a common core set of data that will be used across different modules. For purposes of example lets image a complex public event registration, attendance, and reporting solution. For the most simplistic example lets assume that we will have 5 parts to the total solution: An Admin Module for system configuration, a Reporting module for various system reports, an Event Registration module for users to signup for available events, a My Events module where registered users can review their history of registered events and print tickets, and lastly an Event Manager module which allows privileged users to add/edit/delete events from the system. As you can see here, these modules are truly distinct pieces of functionality, however, there is a lot of shared data and shared objects. We really want to create a structure to allow the modules to be isolated as distinct units, but re-use any common code between all modules, and ideally centralizing things for potential future expansion.
My Recommended Solution
As we look at the above solution there are a number of ways that we could do this. However, in my situation I would see this solution as a 5 module solution, with 5 unique projects inside of a single .SLN file. Each distinct DNN Modules. but each with a distinct layout & set dependency. Additionally, when deployed to DNN, all of these modules should be grouped into their own folder within the DesktopModules folder so that you can easily find all parts. As such, I would recommend the following folder/file structure for this solution with only key files identified. The following tree shows the structure of the "Source" folder within TFS from previous recommendations.
-
Admin
- App_LocalResources
- Components
- Jobs
- Models
- Repositories
- Utility
-
- SqlDataProviderFiles
- Admin.dnn
-
EventManager
- App_LocalResources
- EventManager.dnn
-
EventRegistration
- App_LocalResources
- EventRegistration.dnn
-
MyEvents
- App_LocalResources
- MyEvents.dnn
-
Reports
- App_LocalResources
- Reports.dnn
- EventSystem.sln
As you can see from the above structure we centralize the business logic so that we can have all modules reference a single source. By doing this we will prevent any future expansion from causing a circular reference and make it easy for any new developer to find what they are looking for. For larger teams you can put people on their own modules and once data structures are in place they can work mostly isolated from the rest of the team. If you have a common helper that might be useful to other modules, drop it in the Admin project so all modules could benefit from it.
Conclusion & Coming Up
This gives you a simple project structure to follow, something that you can use to help organize projects and keep things safe to support future expansion. By having distinct modules, you have individual manifests for each, individual installers as well which helps to manage deployment. In the coming posts we will talk about strategies for management of localization in enterprise development and continue discussing how with a project structure like the above how we can make a developers life easier when going from Development to Testing. Feel free to share your comments below.
This article was cross-posted to my Personal Blog.