Introduction
Well, it's been a while since I posted and it boils down to the holidays. There's nothing like the holidays to throw your whole life out of whack. If you are like me, then you keep your life as organized as possible and it's the only reason you are able to function. And that got me thinking about this blog post and gave me an idea.
I've been preparing some articles on MVC, and even a presentation. Something I likely will be taking to code camps, and presenting to even my students at HACC. And that got me thinking about how one of the greatest strengths of MVC is the flexibility and ability to organize code into self contained modules. By building this out, we can organize our code into separate pieces of classes and navigation controllers. We can isolate code and maintain loose coupling to make for more testable code.
Now I can't tell you how many times I've seen wonderful code fall apart. Too many times, I've seen people say "we're using MVC" and say that like it guarantees that your code is not only using current technologies but is correct and architected properly. MVC is a framework, just like any other, and that means that just like any framework, it is only as good as the design of the code and the work of the programmers. If there was a technology that guaranteed good code, we'd all be out of a job.
Now that being said, there are lots of developers out there who leverage MVC correctly. They use the proper separation of concerns. They set up their controllers, using a logical grouping of the controllers and controller actions. But that is a whole other post on to itself, and the ways MVC can be abused.
But all that aside, the one place I see the most abuse of basic structure and patterns is JavaScript. For example, let's say you write code like the following in partial view:
<div>
Number 1 : <input type="text" id="Number1" /><br />
Number 2 : <input type="text" id="Number2" /><br />
<input type="button" id="btnAddNumbers" onclick="AddNumbers()" value="Add Numbers" />
</div>
Now like any good developer, you put your JavaScript code in a separate JS file called "Add.js". And it contains the following code:
function AddNumbers() {
var num1 = parseInt($("#Number1").val());
var num2 = parseInt($("#Number2").val());
var total = num1 + num2;
alert(total);
}
Now to most of us, this looks like perfectly fine JavaScript code. Nothing really special here. When you go to add this to a page, you add a reference to the JS file in the head
tag of your page. And all is well, right?
Not quite... see right now, the JavaScript code above is being declared in what is called the Global namespace. Meaning that the code is being declared at the page level, and everything in this function is available to the entire page.
The question is, what happens when another developer writes a partial view with the following HTML:
<div>
Number to increment:<input type="text" id="NumberValue" /><br />
<input type="button" id="btnAdd"
value="Increment Number" onclick="AddNumbers()" />
</div>
And they write the following function:
function AddNumbers()
{
var num = parseInt($("#NumberValue").val());
num = num + 1;
$("#NumberValue").val(num);
}
And they declare their JS at the bottom of the page, thinking that it would load at the end, and insert their partial view into the same view as yours. The question is what is going to happen now? There are two functions declared with the same name. If this were server side code, we would get a compilation error.
But seeing that this is JavaScript, if I entered a "1" in the "Number 1
" textbox, and a "2
" in the "Number 2
" textbox, and clicked the "Add Numbers
" button, I would get a "NaN
" in the "NumberValue
" textbox.
Now why is that? Because when the browser loads the page, it does so from the top down, which means that it replaces the "AddNumbers
" function with the one that does the incrementing. This is because JavaScript handles functions in much the same way as objects. So by declaring it in the global namespace, you are allowing for the potential that your code could be replaced by someone else's.
So what can you do? To be honest, the best option is to scope your JavaScript so that it doesn't sit in the global namespace, and presents this type of situation. You do that by treating a function just like an object, and modify your code in the following manner.
function CalcMath() {
var addNumbers = function ()
{
var num1 = parseInt($("#Number1").val());
var num2 = parseInt($("#Number2").val());
var total = num1 + num2;
alert(total);
}
return {
AddNumbers : addNumbers
}
}
This creates an object called "CalcMath
", and a "method" off of that object called "AddNumbers
". And this allows me to update the button to have the following:
<div>
Number 1 : <input type="text" id="Number1" /><br />
Number 2 : <input type="text" id="Number2" /><br />
<input type="button" id="btnAddNumbers" onclick="CalcMath().AddNumbers()" value="Add Numbers" />
</div>
Now, if someone adds a function called "AddNumbers
", it has no affect on your partial view. This allows for everything to say modular, and separated and keeps other code from impacting your code in the future.
Many of the JavaScript frameworks out there (Angular, Knockout, etc.) are based on this principle, and use it as a foundation for the other benefits they provide.
So that's it for right now, more to come about the presentation, and more specifically more to come on resources for startups, and articles on lessons learned from my own current startup work.