Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




The RSS Reader Project - Fortifying, Testing and Deploying the Application

computers


The RSS Reader Project - Fortifying, Testing and Deploying the Application

(Start: 00:00:07)

Hello and welcome to lesson 16, this is the final video in our series, and you are currently taking a look at snapshot nine. So we want to review what took place over the past hour, hour-and-a-half of the development or so. The first thing that I want to talk about is code cleanliness or organizing your code, and so if we take a look at the code behind in the MainForm.CS, you can see that for example in line eighteen I have the private tools strip button events, comment, and then you begin to see all of the event handlers for the tool strip buttons. If we scroll down to line sixty-four, you can see I have a comment there, menu item events, so I have organized all the menu items together. You can see in line 107 the main event handlers like the MainForm.load folder combo box, selected index and so on are organized together. Then in line 148 you can see the helper methods are all kind of organized together as well. Now in the Visual Basic version of this video, what I have done was used regions to kind of roll up all of these similar methods together. However in C#, the region does not exactly work the same way. You can't put it inside of a class and expect the results to be the same as they are in Visual Basic. However I'm still able to accomplish something similar to organize my code through using the comments. Now why go to all the work of organizing your code and collecting the similar events and methods together? It is really something you do to help yourself in the future. So three days, five days from now, when I look in the code again, it is easy for me to find what I'm looking for. On of the frustrations that you begin to have as you add a significant amount of code to your project is finding things, and so you can cut down on some of that frustration by just taking few minutes, when you need a mental break, to copy and paste your methods and organize them in some way.



(Start: 00:00:07. END: 00:02:14)

Now some people organize all the methods alphabetically. I choose to try to organize the methods 747x234h in some type of a logical container. Any way you do it is fine. Some people have strong opinions about it, but just find a way that works for you and then continue to do that in all of your projects. It also helps other people who will take a look at your code, to kind of see that there is a pattern and they can begin to expect certain things as they review your code. So as you become a more professional code developer, code cleanliness and organization of the code is very important. On a slightly related topic, you'll notice that I have created a series of helper methods, where formerly all the code existed to, for example, add a folder, or delete a folder, edit a folder, to call up those dialogues. So what did I do? I basically took all that code out and I re-factored it into its own method. So if you were to double-click on the "add folder" so that the entire word is highlighted, right-click it and then select go to definition, you can see in line 150 and following all the helper methods that will, for example, add a folder, or in the other cases edit and delete folders. So I have just moved this code. Now, why did I do that? The reason is because I anticipate in the future adding some functionality to the menu item and possibly even adding some contextual menus, and maybe some other shortcuts that may also allow the user to easily add a folder. I do not want to just copy and paste all this code in lines 152 through the end of this method here in line 200. I do not want to just copy and paste that into for example into a menu click event and context menu click event. There is an old adage in software development that says, "You should never write the same code twice." So we're trying to strive to create one method that encapsulates its functionality, then call that method everywhere we need to add a folder. So this is closely related to code organization, making sure your code make sense, as you're combing through your code looking for opportunities to re-factor it in such way that it is more readable and it is more concise.

(Start: 00:02:14. END: 00:04:38)

The next thing that I want to talk about is the strategy that I used for fortifying the code within my application, and we've already talked about declarative exception handling in lesson eleven, specifically how to use the try/catch statement in order to make sure that our applications do not just blow up whenever they encounter a problem. So as you can see from the add folder method in line number 150, this is the method that we have implemented to pop open in the folder dialogue allowing the user to either create or edit a folder name, and you can see that in line number 165 and 167 that we retrieved the result, whether the user clicked on the "OK" button or the "cancel" button, and based on that if they clicked "OK" we're going to add a new folder row to the data set, which in turn will update the underlying data source. So you can see that there are some potential problems here. The first potential problem is in line 172 where we're setting the folder.foldername equal to whatever the user typed in the folder dialogue in the folder name textbox. Now you are not going to really see an exception occur here probably, unless there is some type problem of some nature. What you will see that manifested in those line 174 and 176. So if the user typed in too many characters for the amount of space that we have allocated in the database, we might encounter any exception there, or too few values, and so when we go to actually add that folder row to our data set, we might encounter a problem. Or more likely in line 176 whenever the update method is called of our folder table adapter, we might have a problem then. What kind of problems can occur? The first one would be a folder row that just does not match up with the underlying database.

(Start: 00:04:38. END: 00:06:38)

Maybe the user went in and was playing around with the rssdataset.xsd, or maybe they went into the database and they were making changes to the folder table, or maybe they've opened up the rss.mdf file in another application, creating a lock on that files so that we can't insert a record, or any number of potential problems. So whenever those occur, we do not want the application to simply to blow up. We want to be able to exit gracefully. So what we've done is implement the catch statement in lines 189 through 192. You can see that we're popping open a message box that says, "There is a problem creating a new folder," and then we use the message property of the exception to give them the full text of the problem that was encountered. Now you may want to rethink that. Maybe it is not a good idea to tell the user everything, but this would be a problem that is fairly unexpected. So perhaps we can give them some clues to what the problem is, maybe they can say, "oh yah, I didn't realize that I had another application opened that might be creating lock on the database," and maybe they can self-diagnose the problem that way. Others might choose to taking a more strongly-typed approach to this exception, where they test and discover other potential problems that can happen. What if somebody had a lock on the database, what if the table got deleted? Find the exceptions that are occurring and then create specific catches for those, and then write the appropriate error messages. That would probably be a more production-worthy version of our application if we were to go to that extent, and maybe in future iterations we can debug and test it to the extent that we can find all those very narrowly-defined, small likelihood of actually happening, type of problems and then code for them, but in this particular case we're simply popping open a message box and letting the user know, and hopefully he can diagnose it for himself.

(Start: 00: 06:38. END: 00:08:49)

So what is the significance of this? This is one way that I have implemented the strategy for fortifying my code, and it is a fairly straightforward example where we're popping open the message box if there is a problem. Now there is another example. If we were to open up the RSS manager.cs, and you can see whenever we're working in this process news feed method that I've pretty much encapsulated the entire method in a try/catch method, and we talked about the fact that it is probably not a good idea to always do this, that you might encounter some performance hits if you were to do this a lot, and that this was a method that got used very often within the application. However, this particular method works with several unknowns, for example the internet. What happens when we cannot connect to the internet? What happens when there are lost packets that are not delivered through the internet? What happens when we get an XML document that is malformed or that is not where it used to be? What do we do? We do not want our application to just blow up as we come across this type of news feed that has a problem, or with our own internet connection. We would like the application to exit gracefully. So when those kinds of problems are encountered, what we want to do is handle the problem. You can see there is a different strategy in lines 135 through 138, where I'm simply taking whatever exception was delivered to my catch statement, and then throwing it up to the code that actually called our process news feed method. Why am I doing this, why didn't I just either display the problem in a message box or in status label? The reason is because again I want my RSS manager class to be fairly autonomous and not be dependent on a specific implementation.

(Start: 00: 08:49. END: 00:10:48)

If I were to display a message box in this class, I'm tying that implementation to a specific type of application, a win form application. What if I wanted to use this in another scenario, like for example on a website, or if I wanted to use it on a console application or in like a windows service? It wouldn't make sense to pop open a message box. So we do not want to tie the implementation to our class. Instead I'm going to throw the problem up to the code they called in. So let's go back to our mainform.cs and take a look at the code that actually called this, and I believe the code that calls it is the query channels method. So let's go ahead and find that in our list. So you can see here that the query channels, if you recall from our previous discussion, will go through each individual channel for the currently selected folder or all the folders I guess, and then for the current channel it's going to then call our RSS manager.process news feed, passing in the URL for that channel, and so then we begin to go through each individual news item that is retrieved back from that process news feed method. So I'm going to use this try/catch statement around all of this because again we're working with a database that we may not be able to control whether it is online or not and so on, and notice here in line 561, where I have this little break point here, I'll turn that off, I also have that I'm going to take whatever exception is thrown and then toss it up. So this might have been a little bit of a lazy approach, but ultimately I knew that these query channels would have been called by some other method, that it could not just be called by itself.

(Start: 00: 10:48. END: 00:12:50)

So I'm going to rely on whoever calls this helper method to take care and display the actual problem. So when an exception happens with process news feed, it's going to hit this second catch statement, which will take that same exception and then toss it up one more level. Notice also that I have a finally statement implemented, so I'm setting the progress bar back down to zero. We will talk about the progress bar implementation in just a minute. Let's take a look at finally in our refresh RSS feed click event, that we have the try and we're calling the query channel's method, and then this is where we actually show where the problem was. There was a problem obtaining the news feed, again we're taking the easy route of just using the message property of our exception.

You can see two different styles of approaches implementing the strategy that we got for fortifying our code. So let's move on and talk about one other aspect of providing some user feedback. So for this let's go back to the add folder helper method that we created, and you will notice if we revisit lines 176 through 186 that we have this situation where we're adding a new folder row to our dataset. Then in line 176 we're calling the update method to take that change, that difgram, and apply it back into the underlying data store. In other words save it back into the RSS.MDF file. So one of the things that are returned from the update method is the number of rows that are affected. So I'm just going to save those off. As you see here I've created an integer rows affected, which will give me the number of rows that were affected by the update method. Now if that is greater than zero, that is good news; that means something actually happened. So we're going to give some non-invasive, non-obtrusive notification to the user that a new folder was created, and then you can see after the right-hand side we're going to actually display the new folder name. So where is thing being displayed? If we take a look at mainform.cs at the very bottom, you recall

(Start: 00: 12:50. END: 00:15:32)

in our first snapshot we talked about the status bar, and there is the status bar off to the left-hand side, this progress bar that we'll talk about in just a moment, but next to it and not really is actually a label that is called "status label." So we will use the status label to update the user on things that we think they should know about, but it is not really super important that we need to interrupt their work flow. So almost all Windows applications have this. In fact if you're looking at the Visual C# 2005 Express Edition, you get these little updates in the lower left-hand corner, which is ready. This changes text as you do different things in the tool. Also what line you're currently on, the column, what character, and also you have the insert key on or off and things of that nature. So you get a little of feedback, and that is all we're trying to accomplish here. So just about anywhere where I call this update method, you are going find me saving off the rows affected and then checking to make sure that something actually happened there. Now what becomes debatable is if the data was not saved into database for whatever reason, if the rows affected were equal to zero, then line 185 is going to fire. Why would rows effected equal zero? That would be a scenario where for some reason, the row was not saved to the database, but an exception wasn't triggered. Now why would that happen? I'm not completely sure. I just known in the past that as I've checked rows affected, sometimes that happens. So I do not really need to know that, I just want to prepare for the scenario where it does happen. So I just basically use the status label that non-obtrusive approach again. Just tells that that there was a problem creating the new folder, that we could not save it in the database, and we will leave it at that. Now some might argue that in a situation like that where the user is expecting to see a folder in the list, it might be too subtle to expect them to take a look in the lower left-hand corner to see that, "Oh, this operation was not completed correctly." So that's just a design decision that we need to live with. After several users get a chance to work with my application and I get some feedback, some of them are probably going to like it, that I'm not in their face, so to speak, with all these notifications, and some are going to say, "Hey, it wasn't very obvious to me why my folder was not created." Again I'm just using this particular example, but it could be applied to any other example in the source code.

(Start: 00: 15:32. END: 00:18:14)

So this is just a matter of making the design decision and suffering the consequences, whether good or bad, as a result of it. So you might have a different opinion on it, and in future iterations if you were to this and continue to work with it, you are free to implement it any way that you want it. So let's continue on. One other thing that I wanted to show you is the use of this expand label, let's show it in action here. Let's run the application quickly, and so now you can see that we have our little preview window populated with the actual web page from the RSS news item that is currently selected, and when I click the "expand" label, notice that it pops open internet explorer with that web page loaded in. How do we make this happen? First of all, what I didn't do, (I'm going to shut this down), I didn't use the link label from the toolbox. I think we have already talked about this a little bit, but I ultimately decided that the link label here did not allow me to capture a click event, and so I decided instead use just the label so that I could take more control over how it works. So I simply changed the properties of the label to be blue and underlined to make it look like a hyperlink, and the other thing that I did is that I data-bound a certain property of the label that is actually common to most controls, and that is the tag property.

The tag property is used for any kind of metadata or used to find data that is associated with a control but never is displayed. Now the reason for this is that I need to data-bind it much in the same way that I data-bind any of these textboxes, and then the web browser window as well. So I do not have to write any code that retrieves the data manually from the data set for example. So I can just data bind this non-visible property called this tag that hold the value which is the hyperlink for our news item, and then retrieve that tag whenever somebody clicks on our little label here in order to fire off internet explorer. Let's take a look at the Expandlabel_click event handler. If you take a look in line 592 I'm simply trying to make sure that something is populated inside our expand labels tag property, if not, if the length of the string is equal to zero, then we're just going to exit out of this.

(Start: 00 18:14. END: 00:21:04)

Next we're going to attempt to pop open internet explorer by using the system.diagnostics.process class, using start method, passing in the name of the process we want to start. So IExplore is the process name for internet explorer, and then we're also going to pass in as a parameter, the tag property of the expand label, which will contain the link. So we're saying, "Open up internet explorer and default it to this URL." That is what we're doing in line 597, and then if something were to go wrong, we're just simply going to catch the exception and pop open the message box that there is a problem. One other thing that I was able to accomplish in this snapshot was the implementation of the progress bar down at the very bottom of our interface. So for example whenever we click on our refresh RSS feed, now watch in the lower left-hand corner. You can see that the progress bar goes across, and then we get this update in the status label: RSS feeds updated successfully 44 news items were added. So this gives both a cue to the user that the application is currently busy. This still allows the user to interact with the application, however it just lets the user know that it is currently doing some thing behind the scenes, and then also we get the RSS feeds updated successfully message to give the user some specific information about how many lines were pulled down. So now let's take a look to the code a little bit more, and you'll notice that there are, depending on the spot in code, there are sometimes a lot of comments, and in some cases for example back in our mainform.cs, there are spots where there are not a whole lot of comments. So we might want to take this opportunity to go back through and be a little more diligent about finding spots and opportunities to add some comments, and also make sure our naming conventions for our variables and for our objects are correct. Look at line spacing, if there are too many lines or if there is not enough line spacing; to kind of just clean up the code in general and make it more readable.

(Start: 00 21:04. END: 00:23:32)

Let's talk briefly about testing the application, and this isn't something that is easily demonstrated, but let's talk about some ways that you can test your application and make sure that you have a level of confidence as you give it to other people. Some of the things that you can do to test your application are, for example, go through each of the various fields, for example adding new channels or editing channels and adding and editing folders as well. You might want to attempt to type too many characters, too few characters. Maybe when we're back here on the mainform we just try to click buttons randomly or in a different sequence than we would normally expect or that we've normally been clicking the buttons in. Perhaps we give the application to other people and let them try to bang on it for a little bit, or we try to use the application and turn off the internet, or maybe try to fill up our hard drive and then run the application and have it attempt to save data to the database or move the database. Just see how the application reacts whenever we try to do some mean, nasty things to it.

These are some of the best ways to test your application. Ultimately, however, whenever you let other people use the application, you are going to find the most feedback about how it performs on various operating systems and things of that nature. So that's when, really, as the old saying goes, "The rubber meets the road." But try to find as many friends as possible who will let you install on their computer. People who are running Windows 98, people who are running Windows XP, who are running Windows 2000, or who are running a tablet PC. Just try to test the application on as many different platforms as humanly possible, and also solicit their feedback, or release a beta version for free to the general public and allow them to give you feedback. You will get some harsh comments, but often times you will get some good comments from people who want to see the development of your application go further. So that it is of more utility to them. So now let's talk about how to distribute your application to others.

(Start: 00: 23:32. END: 00:25:56)

So to install your application on somebody else's machine, you are going to want to create an installation program or an install routine. So typically you'll want to deploy the application on a CD ROM or over the internet, and so we have the option of how we want to distribute the application using Visual C# 2005 Express Edition as we'll see in just a moment. But we'll also get the options of what other files to include, dependencies like databases or any art work, bitmap, gif files and so on. So let's go ahead and get started doing that by right-clicking and selecting "properties" from the solution explorer, and then it gives us a series of tabs that allow us to view properties for our project. We're interested in the last tab at the very bottom called "publish." This will allow us to define where we want to publish our application to, and also set some other important information. So let me just move this over a little bit here. Now in our simple scenario, we're going to use the publish wizard in just a moment. The publish wizard button, as you can see, is down near the lower right-hand corner. However we can also essentially do everything that the publish wizard does and more by working straight from this properties window. For example, I can select where I want to publish the application. Currently it is going to attempt to publish it to the local host or the local web server on this computer in a folder called RSS Reader. However by selecting the ellipses buttons off to the right-hand side, I can choose whether I want to install to the file system, to an FTP site, or to a remote site using http or just a local installation of internet information services. We're going to select our desktop for the time being as the place where we're going to install the files. Additionally I can select whether I want to make this application available to users only when there are online, so they have to navigate to a web page and run the application from a web page, or whether they can work with the application offline. So what is the benefit of the first option? The application is available only online? This makes sure that they always have the most up-to-date version of your application, which can cure a lot of headaches in terms of supporting your application. If your application requires changes often, then this might be a good option for you. Also if you want to restrict who can access the application, that might be another reason why you want to install it on web server and make it available only online.

(Start: 0025:56. END: 00:28:41)

However in our case we wanted it to be available offline, available from the start menu as it says. Additionally, we can choose to add additional files, for example any resource files, configuration files, art work as we noted before, databases that are external to our application, but our application relies on to run. We can also set things like how the application gets updated, whether it should check a certain directory on the internet for newer versions so that it can download it. Also we can set other information about the name of our company, the product name, support URL so on. This will get display to user as they are attempting to install this .NET application on the computer to give them some level of confidence that they are installing the application that they did indeed intend to install, and you have some other options as well as you can see for deploying to web server and to a CD and so on. Additionally at the bottom you can see this ability to add versions to your code that will increment automatically each time you publish, and versions are meant to just let the user know which version of code base that they are working with currently. So as a support professional you might ask, "What version of the application are you currently working with?" The user would then be able to look at a help screen or some configuration file that would tell them which version of the application they're working with, and that might help the support individual to determine what the exact nature of the problem is, because it's perhaps a known problem in certain versions of the code base. So let's just go ahead and click the "publish wizard" button for now. We have already selected the location we wish to publish to. This allows us to select how the users will install the application, whether from a web site, from a network path, or UNC path or file share, or finally from a CD ROM or DVD ROM. So I'm going to select for now the CD ROM/DVD ROM option, and we will when burn these files to disc and distribute them to our friends that way.

(Start: 0028:41. END: 00:30:58)

We'll click the "next" button. It asks us if we want to enable the application to check for updates on its own. That is a little bit more advanced functionality that I'm not going to enable in this iteration. So we're going to leave the default selection, the application will not check for updates, and we're ready to publish. I'm going to click the "finish" button. As you can see in the lower left-hand side of the screen now, that the build is in progress, that it's publishing our application, and that it was successful. It opens up automatically the folder, where these applications have been installed. It has been installed to our desktop. So if we were to just close this down and minimize this, we can see now there are series of folders (I'm going to drag them into place over here), and files that comprise our application. So we could take these files and burn them onto a CD or DVD using any software such as Nero or software that is available from Microsoft to do the same thing. What we're going to do is test our installation by double-clicking the setup.exe. We're given an application install security warning, we could avoid this type of warning if we work to include a security certificate in our application when deploying it, again little bit of an advanced topic so we're not going to go into that right now, click the "install" button, and it looks like everything installed successfully, and it automatically pops open our application for us to play around with it. So it looks like we have a successful installation of our application. Now all we need to do is take these files and we need to put them on a network drive or burn them to a CD.

(Start: 00:30:58. END: 00:32:49)

We've come to the end of our sixteen lesson series on developing applications using Visual C# 2005 Express Edition. We started off by building hello world applications and now we're building applications that go out to internet and grab down XML, parse it, save it in the database, display it on screen. We created an install application. We talked about so many issues between here and there, and so I hope that you have enjoyed this process. I want congratulate you for sticking with this and listening to me talked for the last eight hours, but also hopefully following along and learning these things in a very visual way. So just one last plug: please come by learnvisualstudio.net so that you can download more videos, but also on a personal note I just want to wish you success and the best of luck as you continue to develop applications with C#.

Thank you.

(Start: 00: 32:49. END: 00:33:51)


Document Info


Accesari: 1360
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )