Designing an API with the Visual Studio 2005 Class Designer

 

Tony Loton
LOTONtech Limited

March 2005

Summary: Learn how to use the Visual Studio 2005 Class Designer to plan and diagram an API. (18 printed pages)

Download the ClassDesignerSample.exe file.

Contents

Introduction
Class Analysis
Class Design
The Currency Conversion API
Currency Conversion Web Services
Conclusion

Introduction

In this article I'll introduce you to the Class Designer, one of the new visual designers available in Visual Studio 2005 (except Express editions). The Class Designer is not one of the new Distributed System Designers, but it does have some similarities and is complementary in its use.

Figure 1 shows how the Class Designer fits into the big picture in terms of its relationship with the Application Designer.

ms379621.vstsclassdesigner-fig1(en-US,VS.80).gif

Figure 1. Class Designer relationship with the Application Designer

In the forward direction, application definitions from the Application Designer determine the solution structure—as a set of projects—into which the classes that you design with the Class Designer may be placed. In the reverse direction, classes designed using the Class Designer may well become parameters or return types for services provided by the applications you design using the Application Designer. This might sound rather chicken-and-egg but you can always design application services using standard language types (like double, int, and string), and then retrofit the properly designed classes later; or you could design the classes initially as a standalone class library prior to undertaking the application modeling. In this article I'll demonstrate both approaches to some degree.

Before you get the wrong idea, let me emphasize that what I've just described is the possible interrelationship between the Application Designer and the Class Designer. It's not compulsory and it's perfectly possible to use the Class Designer entirely in its own right. In fact, if you're not running the Visual Studio 2005 Team Architect Edition then that's the only option open to you.

This designer is named the Class Designer because its main use is designing class libraries and APIs. That name is also consistent with Unified Modeling Language (UML) terminology. However, classes represent only one of the types that may be represented on class diagrams, along with enumerations, structures, interfaces, and delegates.

In this article, I will often talk about dragging classes onto class diagrams, deleting classes, and so on. As a general rule, whenever I use the term class it may well be shorthand for class, interface, enumeration, delegate, or structure, so keep that in mind. And where it's not the case, I'll try to be more specific.

The article will flow as follows. First, I'll offer an analysis (class) model for my chosen domain. Then I'll address some of the limitations in that model by evolving it into a design model as a basis for implementation. The final design model alone will not constitute an API because it won't actually do anything in terms of functionality, so I'll devise an additional set of classes for the API itself. Finally, I'll tie up the article by relating this work back to the application design that I conceived in my previous article on the Application Designer.

Wherever I show the code equivalent of a pictorial class, the code will be presented using C# notation. Because the style of .NET programming is pretty much the same regardless of the language you choose, my simple code example will be equally accessible if you're a Visual Basic .NET programmer.

In fact, you could reproduce my steps here with Visual Basic processes by creating a VB Class Library when I prompt you to create a C# Class Library. The only real differences you'll notice is some slight terminology differences reflecting the language you're using. Unlike the UML one-size-fits-all approach, Class Designer uses C# terms (like public, protected) when working on C# classes and Visual Basic terms (like Public, Friend) when working with Visual Basic classes.

Class Analysis

In my earlier article, Introduction to the Application Designer, I conceived a Web service, ExchangeRateService, whose purpose it was to provide the latest up-to-date rate of exchange between two specified currencies. I also conceived a separate Web service that would allow an amount specified in one currency to be converted into an amount in another currency. I'll be drawing on that example again here, but as I've just set the scene it's not mandatory for you to re-read the earlier article.

So, what was wrong with those Web services? Well, nothing in the sense that they worked but their usefulness was limited by the fact that each service returned only a single value—the rate of exchange or the converted amount, respectively—as a double value. Okay for one-off conversions, but not so useful if I want to maintain a history of currency conversions recording the fromAmount, the toAmount, the data / time, the rate of exchange at the time, and the two currencies involved.

To help you visualize this concept, I've sketched out a picture (Figure 2) showing the entities that I have in mind.

ms379621.vstsclassdesigner-fig2(en-US,VS.80).gif

Figure 2. Currency Exchange Analysis Entities

An enhanced ExchangeRateService, rather than returning a double value, would return an ExchangeRate entity holding the dateTime, the rate (of exchange), the fromCurrency (code), and toCurrency (code) for which that rate is applicable. That is shown on the right of Figure 2.

An enhanced CurrencyConverterService, rather than returning a double value, would return an ExchangeTransaction entity holding the fromAmount and toAmount of the conversion. That is shown on the left of Figure 2.

I have used the word entities to this point so as to emphasize the fact that this is a first cut analysis, or domain,-model showing what I have in mind. In due course, I'll refine those entities into a design model, at which point the entities will become classes and other types such as enumerations.

Note   If you look closely, you'll see that in fact the CurrencyCode is already marked out as an Enum; as a consequence of using the Visual Studio 2005 Class Designer to draw this analysis model. Had I used another tool for this stage (explained later), then that need not have been the case.

Creating an Analysis Class Diagram

Before you can start doing any kind of class modeling, you need a Visual Studio project containing at least one class diagram. You can add a class diagram to any kind of project, but I chose a Class Library project because I intend to build a reusable class library—or API—to support currency conversion functionality.

So, I use the File | New | New Project menu option to create a new project, and I choose the Class Library template of the C# project types. I name the project CurrencyClassLibrary.

Note   Although I have chosen to demonstrate class design using the C# language, most if not all of what I describe henceforth is equally application to designing classes for Visual Basic and the other .NET languages.

Once a project has been created, one of more class diagrams can be added to the project using the Project | Add New Item menu option. Just choose the Class Diagram template and give it an appropriate name, which for my example is AnalysisClasses.cd.

Once you have a class diagram on display, even an empty one, you will have access to the toolbox shown in Figure 3.

ms379621.vstsclassdesigner-fig3(en-US,VS.80).gif

Figure 3. Class Designer Toolbox

That toolbox provides all of the types—including Enum, Struct, and so, as well as Class—which you can use to populate class diagrams. Remember at the outset that I drew a subtle distinction between types in general and classes specifically? Let's take a closer look at that distinction.

Drawing the Analysis Class Diagram

I'll now provide instructions on how to draw up that initial class diagram using the Visual Studio 2005 Class Designer. In doing so, I'll be building up the diagram that I presented as Figure 2, which you can refer back to as necessary.

Adding the ExchangeTransaction Class

First, I drag a Class type from the toolbox to the class diagram, and name it ExchangeTransaction. I right-click the class on the diagram and choose Add | Property from the context menu. I name that property fromAmount, and then repeat the exercise for the toAmount property.

Notice that a new source file name ExchangeTransaction.cs appears in the Solution Explorer, and contains the following code:

public class ExchangeTransaction
{
  public int fromAmount
  {
    get { throw new System.NotImplementedException(); }
    set {}
  }

public int toAmount
{
    get { throw new System.NotImplementedException(); }
    set {}
  }
}

You can view that code not only by opening the file in Solution Explorer, but also by right-clicking the class on the diagram and choosing View Code from the context menu.

Adding the CurrencyCode Enum

I drag an Enum type from the toolbox to the class diagram, and name it CurrencyCode. I right-click the Enum and choose Add | Member from the context menu. I name that member USD, and then repeat the exercise for the EUR member. For each member I set its equivalent value in the Properties window so that USD=1 and EUR=2.

Notice that a new source file name CurrencyCode.cs has appeared in the Solution Explorer, and contains the following code:

public enum CurrencyCode
{
  USD = 1,
  EUR = 2,
}

Adding the ExchangeRate Class

I drag a Class type from the toolbox to the class diagram, and name it ExchangeRate. I right-click the class on the diagram and choose Add | Field from the context menu. I name that field dateTime, and then repeat the exercise for the rate field. For each field I can use the Class Details window (Figure 4) to set its type.

ms379621.vstsclassdesigner-fig4(en-US,VS.80).gif

Figure 4. Class Details Window

At this point, it's worth saying a little more about the Class Details window. Whereas you can edit some of the class details, including the class name and the member names, directly on the diagram, to be able to edit member types and visibilities (to name a just two) you must use the Class Details window.

Next, I add two properties, just as I did for the ExchangeTransaction class, and I name those properties fromCurrency and toCurrency. I set their types to CurrencyCode.

Notice that a new source file name ExchangeRate.cs has appeared in the Solution Explorer, and contains the following code:

public class ExchangeRate
{
  private double rate;
  private DateTime dateTime;
   
  public CurrencyCode fromCurrency
  {
    get { throw new System.NotImplementedException(); }
    set {}
  }

  public CurrencyCode toCurrency
  {
    get { throw new System.NotImplementedException(); }
    set {}
  }
}

Now the end result of all that activity is a first-cut analysis model to support currency conversions; a model that I'll refine into a design model in due course. If you decided to follow my lead, but your diagram does not show the types of the fields ands properties on each class, you can fix that simply by choosing the Class Diagram | Display Member Types menu option.

Class Analysis Using Another Modeling Tool

Visual Studio 2005 does not (yet) provide a full range of analysis-level diagramming notations and is currently biased towards notations for design, implementation, and deployment.

It's quite possible then that you might continue to use your favorite UML modeling tool to capture requirements and sketch out the initial analysis (or domain) classes. My favorite tool for that purpose is Visio for Enterprise Architects, which will come as no surprise when you discover that I co-authored the book on it.

Note   You can find out about that book at http://www.amazon.com/exec/obidos/tg/detail/-/0764543768.

More objectively, one of the benefits of using Visio or another UML tool initially, even a free one, is that for business and system analysts an investment in the full Visual Studio 2005 suite might be simply too much.

In order to make the transition from class analysis (in another tool) to class design (in Visual Studio 2005), the only requirement of the other tool is that it can generate code in one of the .NET languages. Once you have a set of classes in your chosen language, it is a very simple matter to create class diagrams from that code in Visual Studio 2005.

Just add the source files to your project, and then drag them from the Solution Explorer directly on to a class diagram. You can create an empty class diagram first by choosing Project | Add New Item and selecting the Class Diagram template, or you can the code files in Solution Explorer and choose View Class Diagram to create a class diagram populated with the selected items.

Class Diagrams as Views on Code

It's worth pointing out that class diagrams are merely views onto the underlying code. This means that you can create as many class diagrams as you like, and you can drag a class from the Solution Explorer onto as many diagrams as you like, without fear that you are duplicating the class each time.

And as views on the code, the diagrams, and the code itself are kept always in sync. This means that you can make changes equally using the Class Designer or the Code Editor according to your preferences, those changes being reflected automatically in the other view.

Class Design

Suppose I hadn't constructed the initial analysis class diagram myself, but rather had taken this as input from a business or systems analyst, either as a Visual Studio class diagram or as a Visio diagram, from which generated code and constructed a class diagram in Visual Studio.

It's a good start, no doubt, in terms of explaining to us—the designer / developer—the objects that will be needed to support currency conversions. But the analyst has been a bit sloppy and that class model is not yet suitable as a basis for implementation. Specifically, I can find the following issues that could be addressed:

  • The fields of the ExchangeRate class are not properly encapsulated using properties.
  • The properties of the ExchangeTransaction are not of an appropriate type, currently being int rather than double.
  • The properties of the ExchangeTransaction have no underlying fields from which their values may be derived.
  • The links between the ExchangeRate class and the CurrencyEnum are implicit in the types of the fromCurrency and toCurrency members, but not explicit as associations on the diagram.
  • There is no connection (association) between the ExchangeTransaction and the ExchangeRates, so currently there is no way to record the ExchangeRate on which a particular ExchangeTransaction was based at the time of the transaction.

You may well find some other issues of your own, and, of course, the problems that I have identified were contrived so as to give us some practical work to do here.

Getting Started

If you followed my instructions on how to create the initial class diagram, you'll now have a Visual Studio project containing a class diagram and three C# source files. If you haven't followed my instructions, you'll have an empty project to which you can add the four files provided by me for your convenience: AnalysisClasses.cd, CurrencyCode.cs, ExchangeRate.cs, and ExchangeTransaction.cs.

Now, I'll create a new class diagram named DesignClasses.cd by right-clicking the project in Solution Explorer, choosing Add | New Item, and selecting the Class Diagram template. Then I drag the three classes—actually their source files—from the Solution Explorer onto the new diagram.

From Analysis Classes to Design Classes

I'll set about evolving the analysis class diagram into a design class diagram by addressing the issues listed above. To save reproducing an almost identical figure at each step, I'll start by showing the end result once in Figure 5. You can refer back to this diagram when I prompt you to do so, to see the effects of the changes.

ms379621.vstsclassdesigner-fig5(en-US,VS.80).gif

Figure 5. Currency Exchange Design Classes

Changing the Types of Fields or Properties

The first issue I need to address is the types of the fromAmount and toAmount properties on the ExchangeTransaction, which would be better as doubles than ints. As shown in Figure 6, I can use the Class Details window to change the type of any member property or field.

ms379621.vstsclassdesigner-fig6(en-US,VS.80).gif

Figure 6. Change a member type in the Class Details Window

If you do not see the Class Details window when you click a class, you can always select menu option View | Other Windows | Class Details, or by right-clicking the class and using the context menu option.

Implementing Properties

The fromAmount and toAmount properties of the ExchangeTransaction class have so far not been implemented. That is, there are no underlying fields or other mechanisms for deriving the values that should be returned for those properties. Not to mention nowhere to store the values of those properties.

In order to implement those properties, I open the code view (right-click the ExchangeTransaction class and choose View Code) and make the C# source code read as follows:

public class ExchangeTransaction
{
  private double frmAmt;
  private double toAmt;
   
  public double fromAmount
  {
    get { return fromAmt; }
    set { frmAmt = value; }
  }

  public double toAmount
  {
    get { return toAmt; }
    set { toAmt = value; }
  }
}

I've made that change entirely in code to emphasize the fact that changes may be made equally in code or on the diagrams. The two views are completely interchangeable. So, while the diagram will not show the implementations of the get and set methods, it will automatically show the two new fields of the ExchangeTransaction class, not only on the current design class diagram, but also back on the original analysis class diagram.

Encapsulating Fields with Properties

On the ExchangeRate class I have the same issue, but in reverse, two fields with no encapsulating properties. That problem could be fixed in code too, but I want to tell you about you a more interesting approach.

I can right-click any field on a class diagram and choose Refactor | Encapsulate Field from the context menu to yield the dialog shown in Figure 7.

ms379621.vstsclassdesigner-fig7(en-US,VS.80).gif

Figure 7. Encapsulate Field dialog

That dialog is inviting me to create a new property named DataTime to encapsulate the field named dateTime; so I accept that and then do the same to encapsulate the rate field.

You can see the result on the diagram by referring back to Figure 5. The result in code is:

public class ExchangeRate
{
  private double rate;
  public double Rate
  { get { return rate; } set { rate = value; } }

  private DateTime dateTime;

  public DateTime DateTime
  { get { return dateTime; } set { dateTime = value; } }
}

Visualizing Associations

If you look back at the original analysis class diagram (Figure 2), you'll see that the ExchangeRate class has two properties, fromCurrency and toCurrency, both of type CurrencyCode. The same diagram shows the CurrencyCode as an Enum, so we can see the allowed values for that property.

In the design class diagram (Figure 5), you can see that the properties are no longer visible, but that two suitable association lines have been drawn between the ExchangeRate class and the CurrencyCode Enum. That's a much more intuitive way of showing the relationship between the exchange rate and the currency codes, and something that you'll be very familiar with if you've used UML.

Switching between the "property" representation and the "association" representation is simply a matter of right-clicking each of the properties and choosing Show As Association from the context menu; and to switch back you can right-click an association line and choose Show As Property from the context menu. These two views are a matter of preference and are indistinguishable in code.

Note   Some UML tools provide this feature in a different way. They allow member types to be represented either as attributes (like properties) or as associations according to predefined rules as to which types are basic types. For example, a String object may be specified as a basic type so that all strings are shown in UML always as attributes, rather than associations to a String class.

There's an additional association that I'd like to add, which is an association between the ExchangeTransaction class and the ExchangeRate class. This is so that for any exchange transaction I can determine not only the from—and to- amounts but also the rate of exchange in force at the time of the conversion—plus the two currencies that were involved.

Because this association does not currently exist, I must add it by selecting the Association item from the Toolbox, clicking the ExchangeTransaction class, and then dragging to the ExchangeRate class. I could rename this association, but the default name of ExchangeRate is just fine.

The end result of all this work is the diagram that I presented at the outset as Figure 5.

Implementing Properties (Revisited)

While the Class Designer may be new to you, as software professionals there's a good chance that some of you will have spotted another opportunity for rationalization now that the last association has been formed.

There's really no need to hold the toAmt field on the ExchangeTransaction class any more because the toAmount may be calculated from the fromAmt and the benefit of the ExchangeRate association / property. So, the toAmt field could be deleted and the toAmount property could be implemented as follows:

public double toAmount
{
  get
  {
    // return toAmt;
    return fromAmt * ExchangeRate.Rate;
  }
}

Notice also that because I'm now calculating the toAmount, the property should now be read-only. That is, with no "set" block. I'll leave this modification to your own judgment.

The Currency Conversion API

I did imply that in this article I'd be designing an API, which you probably took to mean one or more objects that provide useful functionality in a given context. So far I've designed an object model to support an API, but not the API itself.

The API will comprise two classes:

  1. A BureauDeChange class that will provide exchange rate information between any two currencies, using a getExchangeRate method.
  2. A CurrencyConverter class that will provide a number of methods to convert amounts in one currency to amounts in another currency.

For the BureauDeChange at least, I'd like to allow for multiple implementations using an extensible API. That way, several vendors could compete to provide the exchange rate functionality and we could choose the one that offered the best value service.

I'll actually define the BureauDeChange as an interface with a sample implementation. Not only so that I can demonstrate interfaces on class diagrams (my real motivation), but also because interface modeling—as opposed to class modeling—is commendable technique in its own right.

I'm not anticipating multiple implementations of the CurrencyConverter, so I'll model it simply as a class.

Once again, I'll show you the resulting diagram first so you know what to expect, and so that I can refer back to it as needed. Figure 8 shows the class diagram APIClasses.cd.

ms379621.vstsclassdesigner-fig8(en-US,VS.80).gif

Figure 8. API Classes

The first step is to create a new class diagram with the name APIClasses.cd, which will become Figure 8. You know how.

BureauDeChange Interface and Implementation Class

First, I drag an Interface type from the Toolbox onto the diagram, and name it IBureaDeChange. I then use the Class Details window to add a method named getExchangeRate and having the return type parameters shown in Figure 9.

ms379621.vstsclassdesigner-fig9(en-US,VS.80).gif

Figure 9. Class Details for IBureauDeChange

Notice that the parameter types and the return type correspond with (domain) design classes that I defined earlier, thus combining the object model with the API that provides services based around those objects.

Now I need to create a concrete implementation of that interface. I drag a Class type from the Toolbox onto the diagram and name it BureauDeChange. I click the Inheritance item on the Toolbox, click the BureauDeChange class, then click the IBureauDeChange interface; to indicate that the class implements the interface. As you can see in Figure 9, the end result is that an IBureauDeChange interface "lollipop" shape appears attached to the BureauDeChange class. Class Designer will automatically provide method stubs on the class for the methods defined in the interface.

CurrencyConverter Class

To complete the API class diagram I:

  • Drag a Class type from the Toolbox to the diagram and name it CurrencyConverter.
  • Add three methods to that class using the Class Details window as shown in Figure 10.
  • Draw an association between the CurrencyConverter class and the IBureaDeChange interface using the Association item from the Toolbox.

ms379621.vstsclassdesigner-fig10(en-US,VS.80).gif

Figure 10. Class Details for CurrencyConverter

The association line shows that the CurrencyConverter class depends on the services provided by a class that implements the IBureaDeChange interface, which in fact need not be the default BureauDeChange implementation class that I have provided.

Notice also that, once again, this API class uses classes from the object design model as its parameters and return types.

Currency Conversion Web Services

At this point, I have analyzed and then designed a domain object model providing currency conversion entities, plus a set of API classes that provide currency conversion functionality based on those domain classes.

That API has been designed as a set of regular .NET classes and interfaces to be invoked directly from within the same program instance. That was a good way to demonstrate the Class Designer in action, but maybe not the way I'd like this API ultimately to provide its services.

If you read my first article in the series, then these API classes will seem rather familiar. Take a look at Figure 11, which is one of the figures from that article, and you'll see what I mean.

ms379621.vstsclassdesigner-fig11(en-US,VS.80).gif

Figure 11. Currency Conversion Web Services

My idea there was to design a BureauDeChange Web application having an ExchangeRateService Web service that would provide exchange rate information, and a CurrencyConversion Web application having USDollarService and EuroService Web services that would provide currency conversion functionality. In all cases, providing functionality that could be invoked remotely rather than from within the same program instance.

When I designed those Web services applications, I specified the parameters and return types as simple ints, doubles, and so on. This is where I come full circle by suggesting the those Web services could be enhanced, and hence benefit from my class design work, by using the domain objects—ExchangeTransaction, ExchangeRate, and CurrencyCode—as the return and parameter types. Furthermore, to save implementing similar functionality both as Web services and as standard classes, the implementations of those services could act as simple facades that delegate to the API classes I've designed here.

Conclusion

In this article, I have followed a logical progression from class analysis (which may be performed using the Visual Studio 2005 Class Designer) to class design (for which Visual Studio Class Designer is mandatory as the vital link to implementation).

But don't think that Class Designer is limited to that initial class design usage scenario. Version 1 of Class Designer has been optimized for several additional usage scenarios including visualization of existing code, refactoring (also touched on in this article), and drawing diagrams for documentation purposes.

The initial analysis and design was for a domain object model that formed the basis of an API, but which only became an API when I designed additional classes that provide services based on that object model.

Those services may be provided simply as methods on regular classes, or as true services such as Web services, which is how I tied together my articles in this series by relating the work done here back to the work done in my earlier article.

Tony Loton is an MCP who wears various hats as Principal Consultant / Director of LOTONtech Limited (www.lotontech.com), as Principal Consultant / Head of Microsoft Practice at Cogenture (www.cogenture.com), and as Associate Lecturer with the UK's Open University. He is currently co-authoring the book Professional Visual Studio 2005 Team System (ISBN 0764584367) to be published by Wiley / Wrox in summer 2005.
Show: