Earlier this week as I was driving to San Francisco Airport with Scott Willhite and Rob Chartier, the discussion turned to the frustrations of “modern” vehicles and I realized it was the perfect metaphor for a problem which has been on my mind a lot lately – a problem which started small ( as most do ) and has grown continuously over the past decade. The problem I am talking about is Complexity… please give me a moment as I try to explain…
Most of us have been reliant on the wonderful invention known as the internal combustion engine all of our lives. If you are like me, you have probably owned quite a few vehicles over the years; some new and some used, and each with their own unique features and failures. And like everything else in this rapidly evolving world, automobiles have not been immune to the effects of technology.
I remember a day when I could open the hood of my vehicle and I could actually recognize all of the major engine components. In fact, I could even spend a few hours on the weekend and do a complete tune-up – changing the oil and filter, replacing the spark plugs, checking the radiator fluid level, evaluating the electrical connections and water level in the battery, possibly replacing the air filter, etc… Armed with a Do-It-Yourself manual I could even do minor repairs myself, in the comfort of my home garage with a basic set of mechanic’s tools.
However, as automobiles have evolved, they have become much more sophisticated. When I open the hood now, I have a hard time recognizing the engine at all. It’s various components have become so obscured and crowded by plastic shielding, emissions controls, wiring, sensors, and computers that it is next to impossible for a novice to do any sort of maintenance or repairs. In fact, even if you could decipher the maze of components, you would likely not have the advanced tools or gadgets necessary to actually do the work. This new era is great for the professional mechanics and dealers, with their limited warranties and ‘competitive shop rates’, but not so great for the average consumer. In fact, I would have to say that I probably pay more now on regular maintenance for my ‘new’ vehicle ( still under warranty ) than I used to pay for significant repairs to my used vehicles of the past.
So how does this relate to software?
Well, if you go back 10 years and look at the complexity of a typical web application, you would notice that the architecture was generally much simpler than it is today. I recently came across a package containing the original IBuySpy Portal source code from 2001 and it was a mere 770 KB, including documentation! The transition from Classic ASP to ASP.NET was all about Productivity and the ASP.NET platform was eagerly embraced by software developers who wanted to “do more with less” ( if I remember correctly, this was even an official Microsoft marketing slogan used in those days ). The Web Forms model combined with XCopy deployment eliminated most of the headache of Classic ASP/COM and was truly an innovative approach to solving the complications of a stateless programming environment.
When ASP.NET 2.0 shipped in 2005, Microsoft made further strides in terms of making web development even simpler. The introduction of the Web Site Project type, without any requirement for a “project” file, was aimed squarely at the beginner or “productivity” developer. Reducing configuration and lowering the barrier to entry with the introduction of Visual Web Developer and SQL Express was a highly effective strategy for engaging with the “scripter” developer community.
However, it could be argued that since the launch of ASP.NET 2.0, not nearly as much emphasis has been placed on simplicity. Rather, the focus has been on enterprise software development, as ASP.NET matured to become a well respected enterprise platform which includes a wealth of sophisticated professional features. Unfortunately, these advancements came at the expense of simplicity, and since Microsoft is such an influential force, it also motivated many of the more vocal, elite software developers in the ecosystem to carry the enterprise torch ( ie. MVC, etc… ) – in the process marginalizing and neglecting the largest audience of software developers on the planet; the scripters and productivity developers. Microsoft has now recognized this problem and is responding with tools like WebMatrix and Razor in order to be more attractive to this group.
The DotNetNuke development community has not been immune to this problem. In the early days of the project, the level of skill and amount of effort to create a module was minimal. This led to a lot of adoption by scripters and productivity developers which resulted in a large, vibrant developer ecosystem. However, as we embraced new patterns and practices ( ie. WAP, MVP, etc… ) and tried to stay abreast of industry trends, the barrier to entry got constantly higher and the level of complexity increased significantly as well.
Now, I should point out that the core platform never actually dropped support for any of the more simple module development techniques. Rather, we simply stopped using them as we gradually replaced all of the core modules with more modern patterns. Books and articles focused on the new methodologies and promoted the benefits of more rigorous enterprise software development practices. Older techniques fell into obscurity and I would bet that most DotNetNuke developers today have no idea that there are some simpler techniques which can be effectively utilized in certain business scenarios to reduce complexity and increase productivity.
I am going share such an example now, but first let’s clear up a common misconception I often hear in the DotNetNuke community. Because there are thousands of third party modules which are commercially available for the DotNetNuke platform, most people tend to think that the common module development scenario is an ISV who wants to build products to sell to DotNetNuke consumers. In fact, this is not the case. The far more common module development scenario is the productivity developer who gets asked to automate or implement some custom business requirement which is specific to their organization. In this scenario there is no intent to productize the module for resale. Rather, it is built for internal usage only – and there are hundreds of thousands of modules such as this in existence today.
So let’s assume the identity of a productivity developer for a moment…
We work for a company which offers a variety of products and services and we want to better engage with our customers. We are not a multi-national organization; therefore, we only need to focus on English communications. We have standardized on the Microsoft technology stack and as a result, we only expect to utilize SQL Server as our back-end database. We like the idea of being very agile and responsive and we have few IT restrictions other than the typical best practices for ensuring the integrity of our infrastructure. We do not intend to share the modules we build outside of the company, so protection of IP is not an issue. We want to take advantage of the standard DotNetNuke packaging model for simple, predictable deployment. We have limited development resources, no formal QA resources, more internal software projects than we can reasonably handle, and pressure from the management team to get results as quickly as possible. Sound familiar?
The requirements which we have been given by management is to create a module which allows customers to submit suggestions on how the organization could improve our products or services. Then, in the spirit of UserVoice, allow each customer to have a specific number of votes which they can apply to the various suggestions, and allow them to apply more than one vote to a single suggestion if they so desire. This “crowd-sourcing” concept will allow the most valuable suggestions to rise to the top of the list. Also, in the spirit of StackOverflow, allow customers to comment on the suggestions and vote various comments up or down depending on how well they relate to the associated suggestion.
There are a variety of approaches which can be used to create modules in DotNetNuke. The most common patterns are the WSP model, the WAP model, and the MVP model. Each of these have their own unique advantages and disadvantages. Personally, I find the WSP model is best suited for internal development efforts and WAP or MVP is best for creating commercial products for distribution – however, every developer should choose the model which best matches their skillset as well as the needs of the customer.
In the scenario we are dealing with in this article, Productivity is the most critical aspect to consider. We need an approach which is easy to understand and configure, allows for simple support and maintenance, and expedites our time to market. So, I am actually not going to use any of the more common module development techniques described above. Instead, I am going to go “old school” and I am going to utilize a mixture of “inline scripting” combined with the WSP model.
“Inline scripting” in ASP.NET has been supported since the 1.0 days. It was originally included to ease the transition for Classic ASP developers. Over time, the code-behind model took over as the predominant pattern for ASP.NET development; however, in-line scripting still remained a first class citizen in terms of support within the IDE and run-time. In-line scripting is a model which should feel very comfortable to those developers who have any experience with LAMP development ( ie. PHP, Perl, Python ) or CMS systems like Drupal or Joomla. It is a very “hackable” model which is less intimidating for beginners. It is also true that most veteran Microsoft web developers will have an extreme reaction to inline scripting, dismissing it as “spaghetti” ( a reputation it earned in the 1990’s because it does have the flexibility to be abused ).
In DotNetNuke, the basic structure of an in-line script user control ( * .ascx ) to be used as part of a module is as follows:
So let’s build this module…
We are going to utilize the strengths of the framework and make DotNetNuke do a lot of the heavy lifting for us. Since we are only going to support a SQL Server database, we can skip the whole DataProvider model and utilize the DAL+ methods in the core. And with a requirement for English-only, we can bypass localization altogether. Rather than hand-coding HTML output and dealing with complicated state management, we will take full advantage of ASP.NET web controls and their event models. The final product is displayed below:
And the source code package for this module can be downloaded from the DotNetNuke Forge. It will only work with DotNetNuke 5.5, as it utilizes some of the new API methods for loading a user’s profile photo.
Out of curiosity I decided to compare the folder structure and number of files in our “Inline Module” to an equivalent WSP module which utilizes all of the “standard” DotNetNuke approaches for module development. The results were quite dramatic. The WSP Module contained 28 files whereas the Inline Script Module contained 8 files. Yet there was no significant difference in functionality:
I hope you have found this article useful in demonstrating the incredible flexibility when it comes to creating extensions for the DotNetNuke platform. Inline Modules are a model which can be utilized within some organizations to achieve higher productivity and quicker results. They also serve as a great entry point for beginners who want to test the development experience of the DotNetNuke platform.