Sunday, November 27, 2005
Custom Types in .NET
I recently discussed an interesting problem with a customer that I thought was worth sharing here. This particular customer has a system that (among many other things) measures things. Such as the length (or dimensions) of a wooden bar. While this in itself is a pretty trivial problem, things get pretty tricky, because the system handles both metric (meters, centimeters,...) and imperial (feet, inches,...) values, and this is a problem that is much harder to solve than it seems on the surface. Things get tricky because this is not just a mathematical problem, but also a business problem. Here's why: Sometimes, conversions need to be exact. If you need to put glass into an opening that is 10 foot wide and thus turn it into a window, then you will need to tell your European partner to cut it to a width of 304.8cm exactly, or else it will not fit or leave a whole. On the other hand, if you are partaking in an international construction project and plan to cut pieces out of a 10-foot bar, then you will be hard-pressed to find a shop that sells you a 304.8cm bar. Instead, you need to order a 3m bar (it is also rather annoying to go through an entire construction project calling something a "304 centimeter and 8 millimeter bar" instead of a "3 meter bar"). So depending on the situation, conversions need to be done quite differently.
The system currently is written in VFP, and it is a bit of a headache to handle all these different measurements entered in different systems. Every time someone deals with any measurement, one has to fully understand all the details involved and how to handle all the values. Consider a simple example where something that is 5 feet in length needs to be added to something that is 2 meters in length. First, the developer has to determine both values. Then, the developer has to figure out what systems both values are in. The developer also needs to know whether the result is desired in imperial or metric form. The other value then has to be converted based on a set of rules (exact or estimated conversion), and finally, the result as well as information about whether it is in imperial or metric has to be stored in memory or in the database. And of course, this has to be done in every single instance that has anything to do with measurements. Needless to say that in a system that is mainly concerned with keeping track of this stuff, there are many such places. And of course the chances of getting it wrong every now and then are pretty high too.
Another area that is problematic is the UI for all this. What values would we bind the UI controls to? If we have a list of values, how can we easily sum them up (in a report perhaps)? It really is a much more complex scenario than one would think at first.
What could we do in VFP to ease the pain? Well, we could provide objects with methods that take away the implementation complexity. Conversion methods would be useful. The ability to parse a string such as "5m 6cm 13mm" might be useful. Perhaps a method that can convert between two systems in a rounded manner would be nice ("10 feet" is about "3 meters"). Maybe some sort of notification system that allows us to handle an overall system switch from imperial to metric so all the forms know which system to display data in. These types of features would certainly ease the implementation pain. However, they do little to simplify the overall problem. All these methods and objects still need to be invoked whenever one deals with those values. Sure, it gets easier to do the right thing, but the burden of figuring out what the right thing is is still up to the developer.
The .NET Solution
The .NET solution we proposed goes a completely different way that is not available in VFP. It is thus also not entirely obvious to VFP developers (at least initially). So bear with me for a moment...
In .NET, there really is no difference between types and classes. In VFP, things are different. The system provides a number of default data types that are used to store information, and classes are a bit of a different animal altogether. In .NET on the other hand, there is no difference between a String data type, and a custom class or object. The solution to this problem therefore is the creation of a custom data type (which is the same as creating a new class).
Of course, this data type is a bit different in nature from a simple number or string, but this is really not that unusual in .NET. Consider the Guid type. While we normally think of a Guid type as a long sequence of numbers, it really is a combination of multiple individual values that are handled as a single type. The representation of a typical Guid (such as "e319123f-522f-4c05-8aed-f095a5eac253") is really just the string representation of the relatively complex data a Guid maintains internally. Another example for a more complex data type would be a point or vector in 3D space, which is really a combination of 3 different values. On the other hand, it is really just a single atomic data unit.
This is quite a different way of thinking about data than we find it in VFP. In VFP, if we were to store the coordinates of a point in 3D space, we would use 3 numbers. And everyone who used that piece of information would have to know how to handle those three numbers. For instance, if there were 2 separate points in 3D space, and we wanted to calculate where they are relative to each other, then we would have to know how to handle the 6 individual numbers. Quite the nightmare really, and very error-prone. In .NET on the other hand, we would simply have two pieces of data each representing a point, and we could handle them without any knowledge of how to handle 3D coordinates. For instance, we could simply subtract those two coordinates and get their relative positions.
3D coordinates are not something the typical business application developer needs very often. Handling units that could be imperial or metric on the other hand is a more "normal" scenario. And the same basic ideas can be applied here. So how would such a data type work exactly? Well, let's assume we created our new type (class) and called it "Length". I envision that we could then use our Length like so:
Length length1 = new Length("5 foot 6 inch");
Length length2 = new Length("1m 25cm");
Console.WriteLine("Total length: " + (length1 + length2).ToString());
Console.WriteLine("Total length (imperial): " + (length1 + length2).ToImperial().ToString());
Console.WriteLine("Total length: " + (length1 + length2).ToMetric().ToString());
Console.WriteLine("Imperial to Metric: " + length1.ToMetric());
Console.WriteLine(length1.System); // Prints "Imperial"
Console.WriteLine(length1.Value); // Prints "5 foot 6 inch"
Console.WriteLine(length2.System); // Prints "Metric"
Console.WriteLine(length2.Value); // Prints "1m 25cm"
The exact syntax could be slightly different of course and is completely up to our implementation. The key here is that this new data type is completely self contained and integrated into the overall system. It can simply be instantiated and used. Two lengths can be added or subtracted from each other, and all the logic needed to make this happen is contained inside the type. Developers using this type do not have to worry about how to add two values no matter what system they are in. (Operator overloading allows for operations such as length1 + length2).
The type could also have properties that provide access to values in different systems. There can even be an overall switch for the display value by adding a static property (which is shared across all instances of the type), which sets the default for display values:
Length.DisplaySystem = Units.Imperial;
Console.WriteLine(length1.Value); // Prints "5 foot 6 inch"
Console.WriteLine(length1.DisplayValue); // Prints "5 foot 6 inch"
Console.WriteLine(length1.RoundedValue); // Prints "5 foot 6 inch"
Length.DisplaySystem = Units.Metric;
Console.WriteLine(length1.Value); // Prints "5 foot 6 inch"
Console.WriteLine(length1.DisplayValue); // Prints "1m 67cm 64mm"
Console.WriteLine(length1.RoundedValue); // Prints something like "1m 65cm (est!)"
Creating such a custom type allows us to keep all the logic that goes with length calculations in the business layer where it belongs. UI controls simply bind to this new data type. In fact, the UI has no concept of this type being different from a standard type such as a string or a decimal.
The remaining question is how to store this information. Our new type stores more than one piece of information (at the very least, it would store the value and the system). In a database such as SQL Server 2000, the internal values need to be split into their individual parts and stored in separate fields. In SQL Server 2005 on the other hand, the custom type can also be defined in SQL Server and thus be stored as an atomic (single) unit of data.
Of course, a single blog post can not cover the details of how the implementation of all of this works (this post is already rather lengthy). Perhaps this is a good topic for a future VFPConversion.com paper. However, there already are a few other papers that provide information about some of the involved core concepts:
Posted @ 5:29 PM by Egger, Markus (email@example.com)
Tuesday, November 15, 2005
EPS Is Hiring...
EPS is hiring! For various positions, actually, but the most pressing opening we are trying to fill is the one described here:
The EPS Custom Software Group provides leading edge software solutions and services for Enterprise clients worldwide. We employ world-class talent who continuously research, evaluate and use best of breed methodologies, tools and techniques. Our guiding principle is obsessive dedication to flawlessly accomplishing assignments, working at the highest level while keeping them on time and on budget. The EPS Custom Software Group strives to provide its clients with custom solutions that precisely fit their current needs while retaining the flexibility to grow as business needs change.
EPS Software Corp (www.eps-software.com) is currently accepting resumes for a senior level Requirements Analyst. The position is located in Northwest Houston (Spring), Texas. In this position, you will work directly with clients to determine business logic and produce application requirements. You will also create application design and work closely with the development team defining and monitoring work priorities and scheduling throughout the project lifecycle.
- Experience working directly with clients to produce high level Requirements Documents
- Experience explaining to clients the project technical issues in language that the client understands
- Experience interacting directly with Software Developer teams to produce low level, detailed Use Cases and System Functional Requirements, including UI designs, UML diagrams and data models
- Technical and programming background with Microsoft technologies that include C#, VB .NET, ASP.NET and SQL Server including a strong understanding of object oriented, n-tier systems architecture relating to Windows, Web and database applications
- Experience in the software development lifecycle using RUP as well as Agile application development methodologies
- Experience using software tools (e.g. Excel, Word, Project and Visio) to develop project and system documentation
- Five or more years of experience in business process analysis and software development
- Broad knowledge of business practices and operations
- A four-year college degree in Computer Science, Management Information Systems or a related field
- Expert written and verbal communication and documentation skills.
- Highly organized and able to effectively communicate ideas through conversation and documentation
- Strong interpersonal skills and the ability to lead and motivate project teams and to grow relationships with customers
- Ability to assimilate information from a variety of sources into a form that is targeted to the client/customer as well as to the software development team
- Ability and experience working on multiple tasks and projects simultaneously and demonstrate abilities to establish work priorities and schedules
- Possesses meeting facilitation skills
- Emotional maturity to deal with stressful situations
- Any equivalent combination of education, experience and training that provides the required knowledge, skills, and abilities
If you are interested, contact us at firstname.lastname@example.org.
Posted @ 5:04 PM by Egger, Markus (email@example.com)
Monday, November 14, 2005
Markus' Avalon (WPF) Examples from DevConnections
My Avalon (Windows Presentation Foundation) examples from the recent DevConnections show are now available online.
Here's the link to my blog posting with the examples:
The Windows Presentation Foundation (formerly known as "Avalon") is the WinFX-generation user interface technology that replaces current Windows UI. (Think of WinFX as ".NET Framework 3.0"). This technology is entirely based on the Managed Platform (".NET") and thus only available for .NET developers.
Posted @ 1:59 PM by Egger, Markus (firstname.lastname@example.org)