Sunday, January 20, 2008 12:39 AM
Back in December, I had a blog post around Sub Sonic and how I wished there was a separation between the UI and DAL...to which many people didn't really understand what I was asking for or what I was trying to do. And in turn, I realized that my issue had more to do with how ASP.NET in general is structured and not any particular framework (i.e. Sub Sonic) which just play in the sandbox their given.
.NET gains a lot of its power from how flexible it is, and how much leeway we as developers have in creating solutions with it. It is totally possible for us to create a fully data-aware, interactive, business application without writing any code and using all the designers drag and drop controls for everything from setting up the UI to configuring our database connections, to binding and manipulating data. But just because you can doesn't mean you *should*. For small applications, prototypes, or one-offs that you know will never grow, this is fine...or is it? Should we be ok with cutting architecture corners in the name of quick-fixing an app?
My opinion is that we should not; that many of the issues we face in maintaining our applications could be avoided if we followed proper architecture guidelines. I also don't think that enforcing this idea adds any amount of extra time to a project, especially when you gauge it against what happens afterwards when change requests flood in and teams have to try and update an application without breaking it in the process (been there, done that).
So let's get back to ASP.NET. The issue I had originally, and still do, is with the idea of the connection strings being accessed from the web.config file. The argument some made was that all code, because its being run as part of an overall ASP.NET application, should be considered the same *context*...which in this case is under ASP.NET. Therefore any code that accesses your data access layer should retrieve that value from the web applications config file. The problem however is that under this model there's nothing stopping code from the UI or other code that's part of this same context to use that value as well. Temptation can set in ("Oh, we don't need to write a whole class and access it to get this data...we'll just throw a sql connection object on the webform and bind it that way").
So by putting the connection string in the web.config file, you've now coupled your application with a database as well as a database implementation. If the database vendor changes, then you update the DAL as well as the config file so the DAL works property (i.e. you switch from SQL to Oracle).
"Well D'Arcy, what would you propose as a solution to this if its such a big deal?"
One option would be to store the database information as part of the config file for the DAL component.
Waaaait a second...this isn't possible though! Even if you do create a config file for the DAL, any configuration requests will default to the web.config file and effectively make any DLL configuration specific settings mute. At least, that's what most people will tell you.
The reality is that there is a way to add configuration values to your assembly...but there's a slight catch. In an assembly project you can add settings to the settings file. This in turn gets output to an app.config file within your assembly. Upon compiling, the values end up being written within your assembly, and your code can access them REGARDLESS of the "context" that its running in.
This means that none of your code outside your DAL have any clue as to what database is accessed, what type of database it is, etc. Everything goes through the DAL...everything is encapsulated.
Now here's where the discussion turns religious to an extent. The act of using the Settings file is a few steps up from hardcoding a value into your code and accessing it, isn't it? I mean, it's not actually reading from a config file at run time, its compiling the values directly into your assembly. But let's think through some realities here:
Connection String stored in....
Assembly Settings File
- The value is accessible to the assembly without needing to reference the application in context's config file
- All database interaction is abstracted away from the UI and other layers consuming the DAL
- Switching database providers is merely replacing an assembly; no other settings at the app level are required
- Changes to the configuration file will require a re-build of the project
- Unless you obfiscate your assembly, tools like reflector can view the values within the code
- Value is easily accessible and can be altered quickly if kept in plain text mode...which they shouldn't be in though.
- Code from within the web application context can access those values
- Changes to the connection string value will require the conn-string portion of the file to be re-encrypted (you DO encrypt all your sensitive data in your web.config file don't you?)
- Code needs to know what names are associated with the configuration files
- Code from within the web application context can access those values (double edged sword)
Because your code needs to be aware of the config value names, its now coupled with your UI code...doesn't matter if you've split it out into separate assemblies. Now, what if you wanted to re-use that assembly in a Windows app, or a Mobile app? You better make sure you re-created those variable names properly in your application.config file. So now not only is your assembly coupled to your app, but any application that ends up using that assembly is coupled to each other!
I guess what I'm trying to figure out is why so many consider hard coding values a horrible thing, and yet all we're really doing with config files is creating a less-secure place to store values that we'd otherwise hard code in *and* handcuff our assemblies to our UI implementation. Config files are becoming a dumping ground for any setting that needs to be available across *all* tiers and not just the UI. Assemblies solved the DLL Hell problem, but config files seem to be the next evolution in .ini files.
Anyway, I wanted to post something that better explained what it was I was searching for in my earlier posts, and I hope this answered that. Feel free to post your thoughts, I look forward to them.