Monday, December 15, 2008

Automatic Property Validation

If you've seen any of the entities in the solution lately, you will undoubtedly run into code like this:
/// 
/// Gets or sets the consignee identifier for this shipment.
/// 
[PropertyValidation(IsRequired = true)]
[PropertyTranslation("int_ConsigneeId")]
public int? ConsigneeID { get; set; }
The PropertyValidation attribute tells the framework what rules to follow for data assigned to this property. In the above case, this field must have data before this entity is saved.

New Validation Rules

Now, in addition to "IsRequired", you can check properties for a range of values (a minimum and optionally a maximum value). This works for any type of number, date ranges, as well as string lengths. It will be good practice from here on out that you carefully consider the acceptable values for each property of your entity.

For example, any property that references the identifier of some other entity should never have a value less than 1. Therefore, these properties should have a PropertyValidation minimum value of 1.

Here are some examples of interesting validation that can be done now:
/// 
/// References another entity, so a minimum value of 1 is used.
/// 
[PropertyValidation(1)]
public int? ShipperID { get; set; }

/// 
/// References the price of a sellable item, so it would make sense
/// that it cost no less than a penny (but perhaps no more than $25).
/// 
[PropertyValidation(0.01, 25)]
public decimal? PriceOfToy { get; set; }

/// 
/// References the date of a year-two-thousand party. In this case we
/// restrict the party to either New Year's Eve or New Year's Day.
/// 
[PropertyValidation(1999, 12, 31, 2000, 1, 1)]
public DateTime? Y2KPartyDate { get; set; }
Note that if your field is not marked as IsRequired, the framework will only apply these validation rules if a value is specified.

ProTrans Development Environment E-mail

Recently there has been some confusion over the ProTrans E-mail system (how we send e-mails via our coding projects).   To clear this up, we will have a single place to interact with E-mails, and it is an Entity / Controller solution.   Below I have posted a simple example of how to interact with this system, which should be familiar, because it is the same as the rest of our Entity / Controller methodology.   
    [TestMethod]
    public void TestEmailCRUD()
    {
        Email actualEntity = GetEmailEntity();
        //This will queue to the email to be sent...
        this.ControllerEnterprise.EmailSave(actualEntity);
.
.
.
Another feature that this system has, is that when we are in the development and staging environments, it will redirect all of the e-mails to a test address (protransdev@gmail.com) instead of the intended recipient.   This was done so that we can test with production-quality data, including e-mail addresses, and view the results without actually sending the e-mails to customers and vendors.   In order to make sure it is being sent to the correct address, the Controller will place the e-mail address it was supposed to go to inside of the protransdev gmail address like this ( protransdev+realemailaddress~realdomain.com@gmail.com).   Gmail will put an e-mail with that address in the potransdev inbox, and you will be able to see who it was supposed to go to.    The @ in the real e-mail address is replaced by a ~.
If you want to view the e-mails that are bing sent to the new test e-mail address, either login to Gmail.com (and the username is ProTransDev, and the password is one that we have used in other development systems {think small animal, and if you don't get this hint, I'll send it out to everyone soon}), or you can hook in this account to your Outlook if you want to the instructions can be found here.
This new service will eventually replace the current E-mail sender (EmailServiceSolution).   This is being done to get this functionality written within the current framework, and not as a one-off windows service.   Some of the functionality (such as the ability to define SQL to run in the email request itself) are being analyzed and will either be added to the email entity or an alternative will be written...either way, using the email entity is by far the safest and most highly recommened way to send e-mails.   Currently this Controller is pulling the e-mails from the MailMessage table, but this will be changed, and therefore it is not a reliable solution to put e-mails directly in this table without going through the controller.

Wednesday, December 10, 2008

Page Messages

The web architecture now has a unified way of handling errors and displaying messages to the user. This is critical in providing a consistent manner in the way in which we communicate important events to a user. When is this portion of the architecture important?:
  • When our code malfunctions and the user needs to know that something went wrong.
  • When the information the user submits is not in a valid format.
  • When the user successfully accomplishes some task and needs confirmation that everything went okay.
  • When the controller/entity layer decides that the user needs to be warned once before taking certain actions (creating a new shipment where the data looks a bit questionable).


Anytime you need to display something to a user, simply call ShowMessage from within your ASPX page and all of the particular details are taken care of for you. You'll be able to specify whether this message is an error, a warning, or just an informative message.

Secondly, from this point forward, all top-level events must have Try..Catch..End Try statements. Any exception caught should be sent to the HandleException method where the user will be displayed a notice that an error has occurred, and the error will get logged to our database. What is a "top-level event"? Any event that is the direct cause of the user submitting data or built-in wired events in the ASP.NET page lifecycle. (example: Page_Load, cmdSave_Click, etc.).

Exceptions

The only times you should not use ShowMessage for displaying messages to a user are:
  • When you are working with a modal dialog that is built around the Telerik ToolTip control. The reason here is because the message will not look as if it came from the modal dialog; it will be buried under the dialog's shadow.
  • When your message(s) must be displayed right next to other user interface controls for some reason. This is rare -- one case that matches this scenario is the current logon control area.

Tuesday, December 9, 2008

Using Controllers and Entites in Services

     If you have a need to write a new service, and would prefer to write this service using the controller methods and entities library...now you can.  
     As most of you know, the Services portion of the business layer uses NameValuePairs exclusively as a data container, and usually calls other services if it is a "work flow" or "Controller" type service.   Instead of keeping the data in this container, and writing your business logic using Name Value Pairs and directly calling other services, you now have the capability to simply use the Controller methods and entities.   An example of this can be found at in the ProTrans.Enterprise.Services_CSharp project, and the ShipperManagedCallQueue class.
***************
A few things to notice here is that this service does not inherit from the usual Services.Base in the frameworks project, it inherits from ControllerServiceBase, which gives you access to the controllers in the same way that you have access to this via the code-behind on web pages.
Why Is This Important?
This is important, because it will improve our code re-use of the common tasks within our batch processing areas.   Code re-use is important because having a code-reusability mindset lends itself to higher quality software (by virtue of the fact that you will be writing building blocks for the business code, and you will write tests, and with a foundation like that you are setting yourself up to be more successful over time).   Usually you would write a service like this when you are doing some batch process, which brings me to my next question...
When Would I Use This?
    You would use this when the service that you are writing, is one that could simply use a collection of Controller methods.   For instance, if you are writing a service that iterates over a list of Shipments, and makes adjustments and re-saves them...you would not want to rewrite all of the business logic around saving a shipment, you would simply want to call ControllerShipment.ShipmentSave(...), because all of the business rules have been encapsulated and tested inside of this method.   A good candidate for this type of service would be a batch job that needs to be scheduled, or a business process that we have to expose to one of our internal non-.Net applications (like ProTrack).   This is where the service architecture shines, because of it's extensible interface (NameValuePair in NameValuePair out), it can be connected to our legacy systems in a common fashion.   There are many uses for this, but there are also consequences and possibly dangerous issues that need to be thought about and accounted for before making the decision.
How Could This Be Dangerous?
    This is a powerful technique, because it is allowing the NVP-based services to utilize the simplicity and organization of the Controllers and Entities, however, as those of you who have written Controller methods know...they use the NVP services to do their work.   So if you think about this, Controllers are using services, and now we are allowing services to use Controllers, could be dangerous right?   Yes and no...yes academically you could run into a situation where you write a service that is calling a controller method that in turn is calling that same service (this is referred to as a circular reference).   However, the likelihood of this happening is remote, because of the style of services you are using in the Controller methods are vastly different from the style of services you would implement this technique.

Friday, December 5, 2008

How Our Architecture is Like McDonald's

As Andrew has described, there are three basic layers when it comes to the emerging ProTrans architecture.
  • Data: the database structure and SQL for getting information in and out of the database
  • Business: the smart part of the system in charge of making business decisions (i.e. "what needs to happen when someone tries to save a shipment?")
  • Presentation: the user interface that translates what a user wants to accomplish into actions taken on our system
Imagine a customer walks into a McDonald's. All this customer knows is that he wants a tasty Big Mac in his stomach. The cashier (who represents the Presentation layer) looks the customer in the eye and translates his order into a language that the people in the grill understand. It is the duty of the cashier to provide good customer service and handle any misunderstandings the customer has with the menu.

What the cashier hears:

"Hi, yeah I'd like a number one with a Coke. And I want this 'to go', please."

What the cashier tells the people behind the grill:
  • (1) Big Mac
  • (1) Medium Fry
The people working the grill represent the Business layer. They are smart enough to know that a Big Mac is made by adding two all-beef patties, special sauce, lettuce, cheese, etc...on a sesame seed bun. It isn't their responsibility to know what a "number one" means. Likewise, it isn't their responsibility to collect the customer's money. They simply take business requests and do all of the complicated little details to get the job done.

The freezer in the back of the store and the way it is smartly organized represents the Data layer. Whenever the grill workers need to create a Big Mac, they go to the freezer and can quickly locate the ingredients they need (all-beef patties, special sauce, etc.). This keeps the grill area uncluttered and allows people to restock the freezer as it gets low without any grillers even knowing.

Imagine if instead all of these jobs were performed by one person. It would be chaotic and inefficient as people would be running all over each other. Also new employees would be hard to train as they would have to be specialized in all parts of the system.

Keeping things separate allows you to continually improve each section independently without affecting the other parts of the business. The grill team doesn't need to know that there's a special on cheeseburgers on Wednesdays; they can just concentrate on making sandwiches as fast and as best as they can. And if McDonald's ever changes what a "number one" means, only the cashier team is affected.

Tuesday, December 2, 2008

Unit Testing

A Google search for "test-driven development" will lead you to a lot of information on the idea behind creating test scenarios to improve quality in software. These test scenarios are also called "unit tests" because they are designed to test one single software feature. In addition to achieving higher quality in your application, test-driven development is a critical part of keeping a product healthy and maintainable. But I'm getting ahead of myself. What is a unit test and why should you care? Let's say you are writing a method that calculates the average of three numbers:
public double CalculateAverage(int a, int b, int, c)
{
  int sum = a + b + c;
  return sum / 3;
}
One way to ensure that the code you wrote is working effectively is to write some code that calls your method.
[TestMethod]
public void CalculateAverageTest()
{
 double actualAverage = CalculateAverage(2, 3, 4);
 double expectedAverage = (2 + 3 + 4) / 3;

 Assert.AreEqual(expectedAverage, actualAverage);
}
  • "[TestMethod]" tells Visual Studio that this method is a unit test.
  • "expectedAverage" contains the value that I manually calculate without using my CalculateAverage method.
  • "Assert" is a class that contains methods that verify any kind of statement that you want to make -- in this case, that the expected value matches the value computed by my CalculateAverage method.
Look for the "TestSuite" folder in the solution to find all of the projects that contain unit tests. The "ClientControllerTest.cs" file in the ControllersTest_CSharp project contains a lot of good tests for you to look over. Click on the "Test" menu in Visual Studio, then "Windows", and then "Test View" to view the window that lets you run tests. Right-click any of these tests and click "Run" or "Debug". Sometimes writing unit tests can be a bit tricky; especially when your code involves selecting and updating data in the database, because you are relying on data that might be changed by someone else, for instance. The answer to this is: do the best that you can given the importance and complexity of the code you are testing. In other words, do not spend hours trying to properly and exhaustively test code that is doing something very simple. However, if you are writing a critical or highly-used piece of the system, writing thorough unit tests might take days and is probably well worth it. One of the big benefits of this style of development is that it gives you a lot of confidence whenever you need to modify old code. In the example code from this post, what if I come back six months later and change how averages are computed? How can I be sure that my changes won't break other parts of the application? As long as I have unit tests already written, I can simply run those tests and work on my changes until I get a "Passed" result.

Code Organization Part 1 (Folder Structure)

To create quality software many things have to be taken into consideration outside of the algorithms within the source code. One of the most important aspects of quality software development is organization. This series of posts will deal with the main organizational concepts within the ProTrans software world, including but not limited to the web folder structure, the solution and project structures, and even the naming conventions used. If everyone assists in keeping the software-related objects organized it will increase the efficiency in which we code, as well as improve on the readability and therefore maintenance costs associated with development.
First, we will discuss the ProTrans website folder structure. Before I get into the structure too deep, I should mention that a few decisions were made prior to coming up with this folder structure.
The decision to place all of our web applications (for the time-being) into one project was a conscience decision based on the fact that the negative aspects of if we start splitting them up, the management of the configuration files as well as the increased difficulty that comes with deployment out-weighed the benefits. You might have noticed that previously developed web applications such as AccountingReports and OperationReports, are no longer being used, and the web pages inside of these projects have been migrated inside of the ProTransWeb project. There are some costs associated with this decision, such as not having the ability to segregate the web applications on the server into separate application pools, we are opening ourselves up to the ProTransWeb dll growing to be too large. These costs are manageable and can be dealt with later, but in order to get us moving in a positive direction without the added complexity of dealing with multiple projects and solutions, we decided to group all web apps into ProTransWeb.
Now onto the folder structure itself. There is not much to discuss here, other than show the skeleton that we have (which can be downloaded at http://indypro2/PTDev/Shared%20Documents/Enterprise/Architecture/Coding%20Standards/ProTransWeb%20-%20FileSystemStructure.doc). The main points are that there are three levels of presentation pages...public, customer-based, and internal. This is going to help in how we secure our site as well (which I'll discuss in a later post), because our security model is folder based (meaning that there is no security on stuff inside of public, you have to be signed in to get to stuff inside of customer-based, and you have to be signed in and a member of an internal role to be authorized to view a page within the internal node of pages). Inside of the internal folder there are all of the business unit folders. Inside of these business unit folders you should try and group certain multi-page projects, and put reports in the reports folder, etc. When thinking of were to place projects and pages, just think of what is the most simple and intuitive place to put it, and discuss it with your co-developers a little. There are also other system folders to hold things like UserControls, Masterpages, scripts, etc.
If you have any questions about the folder structure or you have a better idea of how to organize it, please let me know.
Thanks

Wednesday, November 26, 2008

Controller Simple Save Entity (Signature)

I want to discuss the thought behind the signature of the Save methods in the Controllers. In later posts, we'll discuss some of the inner-workings of a Save, but for now we will focus on how you should expect to interact with it in your Unit Tests, and in the Presentation Layer.
First, you will notice that there are no Insert and Update methods, just a Save. This was done to simplify the experience of using this framework, as well as move the concern of whether or not this entity previously existed into the Controller Layer and not in the Presentation Layer, which is appropriate since the Presentation should not have business rules in it.
Second...you might be asking yourself how errors are are handled within Save methods. We decided to go with a custom ProTransControllerException. *(An understanding of .Net Exception handling is needed to really grasp what we are doing here, but that is a different discussion...also, we weighed the pros and cons of using a relatively "expensive" technique like throwing Exceptions for validation errors, but for ProTrans the cost was worth the simplicity and standardization that comes with simply throwing the Exception)* The TeachingExample_ControllerSave_Email Unit Test, which exists in the EnterpriseControllerTest in the ControllersTest_CSharp project, has a straight-forward example of how you catch the custom exception, and handle the messages *(I have pasted a sample of the code from this Unit Test below...and again, we are discussing the signature and how to interact with the save methods right now, we will discuss what to do with these messages in your web application at a different time)*.
This save signature is what you will see 80% - 90% of the time, the only other major technique for saving, is advanced saving when you have validation warnings that may or may not be skipped. For the sake of keeping these posts as short and to the point as possible, this technique will be discussed in a seperate post.
[TestMethod]
public void TeachingExample_ControllerSave_Email()
{
    Email emailEntity = new Email();
    try
    {
        //This should fail validation, because the required fields were never set.
        ControllerEnterprise.EmailSave(emailEntity);
    }
    catch (ProTransControllerException ptException)
    {
        //These are the messages that should have been thrown.
        string[] expectedMessages = new string[] {
            "Recipients is required, but was not supplied."
            , "Subject is required, but was not supplied."
            , "Message is required, but was not supplied."};

        //The exception should have the same number of messages
        Assert.AreEqual(expectedMessages.Length, ptException.Messages.Length);

        //Every message should be found in the Messages property of the exception.
        foreach (string curString in expectedMessages)
        {
            Assert.IsTrue(ptException.Messages.Contains(curString));
        }
    }
    catch (Exception ex)
    {
        Assert.Fail(ex.Message);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

Tuesday, November 25, 2008

Lunch and Learn 1 (Overview)

Team,
Thanks for making the first lunch and learn an overall success. Hopefully we are moving toward a time where everyone feeld like they are improving, not only within the ProTrans framework, but as software professionals period. In this first lunch and learn we discussed Seperation of concern as it pertains to the main three layers. This is not a ProTrans specific concept...it is a standard practice widely accepted in the professional software development community across the board (including Java, Ruby, PHP, etc). We are a .Net shop, and within the .Net world/environment, the framework is modling itself to allow for better implementations of this type of software seperation. The days of data sources, business and presentation all on one page will never completely go away from the industry, but it is now (rightfully so) being frowned upon, and better architectures are being put in place so that the "path of least resistence" or the easiest way to do it, is the "right way" (in the very high level sense of code seperation).
Ok, I'll be done with my evangelizing...I have posted a few of the images from the presentation below.

Monday, November 24, 2008

WELCOME

Welcome ProTrans Development team and friends!
We will use this as a central location for informal communication about the "Goings-on" within the architecture group specifically, but not exclusively.   Meaning, when architectural decisions are made or findings are needed to be communicated to the team, they will initially be discussed in this blog.   However, if in the future we would like to extend the blog to discuss more business-related or process-related topics, that will be a good thing.   This is another attempt to improve the communication amungst the team, therefore improving the overall quality of software and even environment.