Thursday, December 13, 2007

View of Web 2.0

Significant workplace inroads for Enterprise 2.0?

Blogs and wikis may finally be seeing fairly widespread “business approved” adoption in the workplace.

http://blogs.zdnet.com/Hinchcliffe/

Friday, October 12, 2007

Enterprise Services

Enterprise Services is the name of the Microsoft application server technology that offers services for distributed solutions. Enterprise Services is based on the COM+ technology that has already been in use for many years. However, instead of wrapping .NET objects as COM objects to use these services, .NET offers extensions for .NET components to take direct advantage of these services. With .NET you get easy access to COM+ services for .NET components.



When to use Enterprise Services

What services you get with this technology

How to create a serviced component to use Enterprise Services

How to deploy COM+ applications

How to use transactions with Enterprise Services

How to use Services without components

Overview
The complexity of Enterprise Services and the different configuration options (many of them are not needed if all the components of the solution are developed with .NET) can be more easily understood if you know the history of Enterprise Services. That's why this section starts with the history of Enterprise Services. After that, you get an overview of the different services offered by this technology so you will know what feature could be useful for your application.

History
Enterprise Services can be traced back to Microsoft Transaction Server (MTS), which was released as an option pack for Windows NT 4.0. MTS extended COM by offering services such as transactions for COM objects. The services could be used by configuring metadata: the configuration of the component defined whether or not a transaction was required. With MTS it was no longer necessary to deal with transactions programmatically. However, MTS had a big disadvantage. COM was not designed to be extensible, so MTS made extensions by overwriting the COM component registry configuration to direct the instantiation of the component to MTS, and some special MTS API calls have been required to instantiate COM objects within MTS. This problem was solved with Windows 2000.

One of the most important features of Windows 2000 was the integration of MTS and COM in a new technology with the name COM+. With Windows 2000, COM+ base services are aware of the context that is needed by COM+ services (previously MTS services), and so the special MTS API calls are no longer needed. With COM+ services some new service functionality is offered in addition to distributed transactions.

Windows 2000 includes COM+ 1.0. COM+ 1.5 is available with Windows XP and Windows Server 2003. COM+ 1.5 adds more features to increase scalability and availability, including application pooling and recycling, and configurable isolation levels.

.NET Enterprise Services allows you to use COM+ services from within .NET components. Support is offered for Windows 2000 and later. When .NET components are run within COM+ applications, no COM callable wrapper is used ; it runs as a .NET component instead. When you install the .NET runtime on an operating system, some runtime extensions are added to COM+ Services. If two .NET components are installed with Enterprise Services, and component A is using component B, COM marshaling is not used; instead the .NET components can invoke each other directly.

Where to Use Enterprise Services
Business applications can be logically separated into presentation, business, and data service layers. The presentation service layer is responsible for user interaction. Here the user can interact with the application to enter and view data. Technologies used with this layer are Windows Forms and ASP.NET Web Forms. The business service layer consists of business rules and data rules. The data service layer interacts with persistent storage. Here you can use components that make use of ADO.NET. Enterprise Services fits both to the business service layer and to the data service layer.


Enterprise Services is also a scalable technology. Using component load balancing makes it possible to distribute the load of the clients across different systems. Component load balancing requires the Microsoft Application Center Server. You can read more information abut the Microsoft Application Center Server at http://www.microsoft.com/applicationcenter.

You can also use Enterprise Services on the client system, because this technology is included in Windows XP.

Contexts
The base functionality behind the services offered by Enterprise Services is the context. The context makes it possible to intercept a method call, and some service functionality can be carried out before the expected method call is invoked.

.NET Remoting contexts also play an important role with Enterprise Services, because these contexts are used for intercepting .NET objects configured with Enterprise Services. However, because COM components can be configured with Enterprise Services in a similar way as with .NET components, the COM+ context exists in conjunction with the.NET Remoting context. This way, a COM component and a .NET component can participate in the same transaction.

Automatic Transactions
The most commonly used feature of Enterprise Services is automatic transactions. With automatic transactions, you needn't start and commit a transaction in the code; an attribute can be applied to a class instead. By using the [Transaction] attribute with the options Required, Supported, RequiresNew, and NotSupported, you can mark a class with the requirements it has for transactions. If you mark the class with the option Required, a transaction is created automatically when a method starts and is committed to or aborted when the root component of the transaction is finished.

Such a declarative way to program is of particular advantage when a complex object model is developed. Here automatic transactions have a big advantage instead of programming transactions manually. Assume you have a Person object with multiple Address and Document objects that are associated with the Person, and you want to store the Person object together with all associated objects in a single transaction. Doing transactions programmatically would mean passing a transaction object to all the related objects so that they can participate in the same transaction. Using transactions declaratively means there is no need to pass the transaction object, because this happens behind the scenes by using the context.

Distributed Transactions
Enterprise Services not only offers automatic transactions, but the transactions can also be distributed across multiple databases. Enterprise Services transactions are enlisted with the Distributed Transaction Coordinator (DTC). The DTC supports databases that make use of the XA protocol, which is a two-phase commit protocol, and is supported by SQL Server and Oracle. A single transaction can span writing data to both a SQL Server and an Oracle database.

Distributed transactions are not only useful with databases, but a single transaction can also span writing data to a database and writing data to a message queue. If one of these two actions fails, a rollback is done with the other action.



Object Pooling

Pooling is another feature offered by Enterprise Services. These services use a pool of threads to answer requests from clients. Object pooling can be used for objects with a long initialization time. With object pooling, objects are created in advance so that clients don't have to wait until the object is initialized.

Role-based Security
Using role-based security allows you to define roles declaratively and define what methods or components can be used from what roles. The system administrator assigns users or user groups to these roles. In the program there is no need to deal with access control lists; instead, roles that are simple strings can be used.

Queued Components
Queued components is an abstraction layer to message queuing. Instead of sending messages to a message queue, the client can invoke methods with a recorder that offers the same methods as a .NET class configured in Enterprise Services. The recorder in turn creates messages that are transferred via a message queue to the server application.

Queued components and message queuing are useful if the client application is running in a disconnected environment (for example, on a laptop that does not always has a connection to the server), or if the request that is sent to the server should be cached before it is forwarded to a different server (for example, to a server of a partner company).

Loosely Coupled Events
how to use events with .NET Remoting n how to use events in a COM environment. With both of these event mechanisms, the client and the server do have a tight connection. This is different with loosely coupled events (LCE). With LCE the COM+ facility is inserted between client and server (see Figure 30-2). The publisher registers the events it will offer with COM+ by defining an event class. Instead of sending the events directly to the client, the publisher sends events to the event class that is registered with the LCE service. The LCE service forwards the events to the subscriber, which is the client application that registered a subscription for the event.



Services without Components
Services without Components is a new feature of COM+ 1.5. With this service it is possible to create a context without the need of configuring a component. By using some classes from the namespace System.EnterpriseServices, the context can be created within a method. Such a context can have transactional requirements associated to automatically deal with transactions that are managed by the DTC.

Nine Tips to Enterprise-proof MSMQ

Since the release of the first version of MSMQ in December of 1997, it has provided the plumbing required by many enterprise applications. Before MSMQ, developers implemented tools with similar functionality using input/output directories with files, SQL Server tables, DCOM, TCP/IP sockets, etc. The major shortcoming in all these approaches was the complexity of delivering a robust system—performance took a back seat. MSMQ's release provided the standardized messaging platform that many projects needed—a great head-start for developers building enterprise solutions.

Unfortunately, MSMQ fell short in delivering the level of performance and robustness required by many projects. As message volume grew, and demand for 'always on' reliability increased, many found MSMQ falling short. However, after many troubleshooting sessions involving Microsoft engineers, important ways of increasing both the performance and robustness of MSMQ emerged. In this article, I've listed these options, arranged as tips that significantly impact messaging performance and tips that improve reliability using MSMQ.

Increasing MSMQ Performance
If you're not already intimately familiar with MSMQ, I encourage you to review the documentation for MSMQ versions 2.0 and 3.0. You can find documentation links in the Related Resources section of this article that outline all the major features. The tips you'll find here don't rehash the documentation; instead, they provide advice widely applicable to most MSMQ installations.

Tip 1: Use Recoverable Messages Only When Necessary
By default, MSMQ processes messages as quickly as possible, at the risk of possibly losing the messages if the machine is rebooted or if the MSMQ service is restarted. MSMQ stores all the messages in memory to increase performance. Unless your application is designed to survive the loss of messages, you really don't have many options—you probably need to make your messages recoverable.

This recoverability comes at a cost. In my unofficial tests, I found that messages took about 3-6 times longer to send when the messages were configured as recoverable. The real difference will depend heavily on the disks you are using on the receiving machine (and on the sending machine if the sender is disconnected from the receiver), but you get the general idea. Below is a listing of the change necessary to configure a message to be recoverable.


Dim msmqMessage As System.Messaging.Message
msmqMessage = New System.Messaging.Message("Hello World")
msmqMessage.Recoverable = True 'default is False


The code required to retrieve recoverable messages is the same as that required to retrieve non-recoverable messages. The receiving application does not treat the messages differently. See the code sample below for an example of retrieving messages.


Dim msmqQueue As System.Messaging.MessageQueue
Dim msmqMessage As System.Messaging.Message
msmqQueue = New MessageQueue( _
"FormatName=OS:testbox\TestQueue")
msmqMessage = msmqQueue.Receive()


Recoverable messages, while they significantly decrease performance, can increase the robustness of the application considerably. If it is important that messages are not lost, then configuring for recoverable messages will help to prevent communications failures.

Tip 2: Do Not Use Journaling

Figure 1. Enabling Journaling: Use the property window of a message queue to enable journaling.
Journaling is a feature that allows a copy of the retrieved message to be copied into a special queue when it is retrieved by the receiving application. The journal messages are stored in a Journal queue associated with the queue the message was retrieved from. This feature is useful mainly for debugging and auditing, and should not be used on production systems except for brief periods. While the performance overhead of retrieving messages from a queue that is configured for Journaling is only about 20% more than retrieving messages without Journaling, the real cost is unexpected problems caused when an unchecked MSMQ service runs out of memory or the machine is out of disk space. There is no measurable difference in sending messages to a queue configured for Journaling; the overhead is incurred when retrieving messages. You can enable journaling on a queue by opening the queue properties and clicking the Enabled checkbox in the Journaling section of the window


Tip 3: Avoid Transactions If Possible
MSMQ supports transactions for environments sensitive to ATOMIC operations. To improve performance when using transactions, MSMQ supports internal transactions—either all messages are sent or none are sent; however, to make the product more extensible, MSMQ also supports COM+-style DTC transactions, known as extexternalernal transactions. This feature allows developers to enlist the sending or receiving of a message in a transaction that involves committing other transactions such as database updates. Unless this is a feature that is absolutely required by your application, steer clear of transactions involving MSMQ. The overhead involved in transaction support for internal transactions is close to 100%. Using DTC-style transactions incur an even higher overhead typical of two-phase commit operations.


MSMQ supports internal transactions using the MessageQueueTransaction object. This object coordinates of message sends and receives inside a transaction boundary. It also exposes methods used for both controlling the outcome of a transaction and monitoring the state of existing transactions. The following code shows an example of sending two messages in the context of an internal MSMQ transaction.


Imports System.Messaging

Dim msmqTransaction As New MessageQueueTransaction()
Dim msmqQueue As New MessageQueue( _
"FormatName=OS:testbox\TestQueue")
Dim msmqMessage1 as New Message
Dim msmqMessage2 as New Message
msmqTransaction.Begin()
Try
msmqQueue.Send(msmqMessage1, msmqTransaction)
msmqQueue.Send(msmqMessage2, msmqTransaction)
msmqTransaction.Commit()
Catch
msmqTransaction.Abort()
Finally
msmqQueue.Close()
End Try


As you can see in the previous code example, MSMQ uses imperative support for internal transactions—that is, you explicitly request transaction services. To support external transactions, you implement a .NET serviced component by inheriting from the System.EnterpriseServices.ServicedComponent class and by setting several .NET Framework attributes that declare support for transactions. External transactions use a declarative model.

The following MSMQSampleApp class shows how to implement declarative external transactions


Imports System.EnterpriseServices





Public Class MSMQSampleApp
Inherits ServicedComponent

Public Function SendShipperNotification() as Boolean

Try
Me.SendMSMQNotification(strCompany, strMessage)
Me.WriteSQLAuditEntry(strCompany, strMessage)
ContextUtil.SetComplete()
Return True;
Catch e As Exception
ContextUtil.SetAbort()
Return False;
End Try

End Function

End Class

This class first declares support for transactions using the appropriate .NET Framework attributes. It then defines a method that both sends an MSMQ message and writes an entry to a database inside the context of an external transaction. As you might expect, either both actions occur, or neither occurs. Unlike internal transactions, where MSMQ brokers the transaction, Microsoft's DTC acts as the transaction broker for external transactions. The example SendShipperNotification function sends a notification message to a shipping company using MSMQ. To maintain consistency the application also writes an audit log entry to a SQL database via the WriteSQLAuditEntry method.

Tip 4: Use Windows Security Sparingly
MSMQ uses the standard Windows security model. You can configure queues to permit only senders and receivers with appropriate security privileges. Security is an ever-increasing issue at most companies. I have found that the tradeoff for including Windows security in messaging is that it takes about 2.5 times as long to send the same messages. By configuring MSMQ not to send the security descriptors associated with the sending application, you can obtain significant performance gains. To configure MSMQ not to send a security descriptor with the message, set the message property AttachSenderID to False (the default is True), for example:


msmqMessage.AttachSenderId = False

Tip 5: Use Private Queues
MSMQ supports both public and private queues. The primary difference is that public queues, and their properties, are published in Active Directory. This makes it easier to find queues based on their name or properties anywhere in an enterprise. I have found this feature to be of little use, since I generally know which queue I am going to send a message to.

I encourage you to use private queues whenever possible. Not only are they slightly more efficient, but they are also less prone to problems with AD (no one has problems with AD do they?). When AD is misbehaving, or when the machine hosting your queues cannot reach the MSMQ service running on one of your AD servers, the public queues hosted on the machine cannot be configured and no queue properties can be obtained. You will be unable to create new queues, delete existing queues, or modify the queues until the issue is resolved.

Tip 6: Use Direct Format Names to Open Queues
When opening queues, MSMQ provides several options for specifying the queue you would like to open. The easiest way to specify a queue name is to use a simple pathname such as testmachine\testqueue. This naming convention specifies that you would like to open a queue named testqueue hosted on a machine named testmachine. When opening a queue in this manner, MSMQ consults the directory service to resolve the location and properties of the queue.

By using direct format names with private queues, you specify the exact queue location and name, circumventing the overhead involved in consulting the directory service. An example of a direct format name is TCP:192.168.100.1TCP:192.168.100.155\private$\TestQueue. There are other ways of specifying a direct format name, for example, you can specify a machine name as in OS:textbox\private$\TestQueue, rather than an IP address. Both direct format names are equivalent, except that the latter incurs the slight overhead of looking up the machine's IP address. To obtain the most reliable and highest performing message queuing environment, use direct format names and private queues whenever possible. This MSDN article provides other examples of format names.


Increasing Reliability
The preceding section discussed MSMQ availability only in cases where higher availability is a factor in increasing performance. This section describes several other ways of making an MSMQ messaging platform more reliable. The following tips don't involve changes to code, but are very useful ways of making MSMQ a more reliable messaging platform.


Tip 7: Avoid Active Directory and Public Queues
When using MSMQ with public queues, the local MSMQ service communicates with the MSMQ directory service running on one of the AD domain controllers—the directory service catalogs settings for all the public queues in the domain. In my experience, there are countless problems with the directory services becoming inoperable—and that prevents access to the public queues (You just have to hope your applications aren't using the queues when this happens). In contrast, private queues do not interact with the domain-wide directory service; only the local MSMQ service knows about the private queue. As such, you must reference private queues using direct format names.

Another problem with when using MSMQ with AD integration is that the local MSMQ service cannot start when it is unable to reach one of the domain-wide directory services. This is true even if you aren't using any public queues. To fix this problem, elect to install MSMQ without Active Directory integration during the install process of MSMQ. If you are trying to increase the availability of your MSMQ installations, I generally recommend using direct format names with private queues after installing MSMQ without Active Directory integration. You will be thankful you chose this route.

Unfortunately, my experience has been that even when you install MSMQ without Active Directory integration, as recommended above, public queues and AD integration functionality returns. While Microsoft Support has not confirmed this behavior, I have witnessed it on several occasions. A recent call to Microsoft revealed a registry key apparently specifically intended to prevent issues of this nature—it prevents MSMQ from using AD integration. To add this value to your registry, add a DWORD entry named AlwaysWithoutDS under the subkey: HKEY_LOCAL_MACHINHKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSMQ \Parameters\Setup. Set the value to 1. Adding the key should prevent MSMQ from ever attempting to use AD's Directory Services functionality and will lead to a more stable MSMQ installation.

Tip 8: Clustering and Load-balancing MSMQ
Using Microsoft's Windows Clustering tool, queues will failover from one machine to another if one of the queue server machines stops functioning normally. The failover process moves the queue and its contents from the failed machine to the backup machine. Microsoft's clustering works, but in my experience, it is difficult to configure correctly and malfunctions often. In addition, to run Microsoft's Cluster Server you must also run Windows Server Enterprise Edition—a costly operating system to license. Together, these problems warrant searching for a replacement.

One alternative to using Microsoft's Cluster Server is to use a third-party IP load-balancing solution, of which several are commercially available. These devices attach to your network like a standard network switch, and once configured, load balance IP sessions among the configured devices. To load-balance MSMQ, you simply need to setup a virtual IP address on the load-balancing device and configure it to load balance port 1801. To connect to an MSMQ queue, sending applications specify the virtual IP address hosted by the load-balancing device, which then distributes the load efficiently across the configured machines hosting the receiving applications. Not only does this increase the capacity of the messages you can process (by letting you just add more machines to the server farm) but it also protects you from downtime events caused by failed servers.

To use a hardware load balancer, you need to create identical queues on each of the servers configured to be used in load balancing, letting the load balancer connect the sending application to any one of the machines in the group. To add an additional layer of robustness, you can also configure all of the receiving applications to monitor the queues of all the other machines in the group, which helps prevent problems when one or more machines is unavailable. The cost for such queue-monitoring on remote machines is high (it's almost always more efficient to read messages from a local queue) but the additional level of availability may be worth the cost.


Tip 9: Set Message Store Quotas

Figure 4. Setting Message Store Quotas: Windows 2000 Server instructions describe how to enable a machine quota to limit the size of the MSMQ messages store.
MSMQ has limitations is limited in on the number and size of the messages it can store on a machine. In most instances, MSMQ versions 1.0 and 2.0 can store no more than about 1.6 GB of messages on a machine. There are ways of overcoming this size limitation, but the your main goal should be to protect MSMQ from problems that arise when the message store size exceeds the amount of space allowed on the machine. When that happens, using a standard MSMQ installation, the MSMQ service will become unresponsive and, if stopped, will not start.

Using machine quotas, you can set a limitation on the size of the message store (see Figure 4 for instructions on configuring a quota for this purpose). Setting such a limit prevents The limitation will prevent MSMQ from receiving any messages until adequate storage space becomes available—the messages queue up on the sending machine. While this does not solve the problem in a way that makes your application more reliable, it helps makes MSMQ more stable in such circumstances. With MSMQ still running, you can purge queues or retrieve messages from queues on the machine until the message store has returned to a manageable size.

MSMQ is an amazingly flexible tool that can provide reliable message queuing, but like any other tool, proper configuration is essential in reaching acceptable performance and availability goals. The suggestions in this article cover only a fraction of the tunable characteristics of MSMQ. If you begin using MSMQ at an enterprise level, I encourage you to browse the additional resources listed in the Related Resources section of this article.

Wednesday, September 26, 2007

debugging

http://blogs.msdn.com/tess/

Saturday, September 22, 2007

Interview Question

Q: How many times a day a clock’s hands overlap?

In any circular motion, if the ratio between 2 fellow is n:1 then for each lap of the slower fellow, faster fellow overlaps him n times, except for the last lap of the slower fellow, where the number of crossings are n-1. (The race just finishes before the n th cross.
slower fellow : hour hand (short)
faster fellow : minuite hand (long)
n = 12
Total laps for hour hand = 2
total overlaps = 12+11 = 23.


Q:If you look at a clock and the time is 3:15, what is the angle between the hour and the minute hands? ( The answer to this is not zero!)

The time is 3:15, i.e. 25% of the time between 3 and 4 has passed. The hour-hand should, by simple mechanical logic, have moved 25% of its total distance between 3 and 4.
The total angle the hand covers is 360%, so the angle covered between 3 and 4 should be 360/12 = 30 degrees.
The minute hand is smack on 3, and the hour hand is a quarter of 30 degrees further on. The angle made between them is thus 30*1/4 = 7.5 degrees


Q:If the probability of observing a car in 30 minutes on a highway is 0.95, what is the probability of observing a car in 10 minutes (assuming constant default probability)?

If you have a solution why do not you share it with us



Q:In a country in which people only want boys, every family continues to have children until they have a boy. if they have a girl, they have another child. if they have a boy, they stop. what is the proportion of boys to
girls in the country?


Assuming both having a boy or a girl are equal in probability then the ratio is 1.



Q:What method would you use to look up a name in a dictionary?

Do you remember that game 20 questions? You have to ask 20 questions to guess a word. The way to cheat is to narrow it down by half every time. The English dictionary has about 500,000 words, meaning you would still have queries to spare.
Yes, it would be boring, but it would go something like this:
Does your word come before the word “marry”? Yes
Does your word come before the word “gerrymander”? You get the point.
Assuming you already know you have to sort, you can binary search at O(log_2 N). For this, say, a trillion, is less than 50.
But its application doesn’t stop there, as it -as well as its cousin ternary search- can help you solve numerical equations (this is actually called bisection). For example, you want to find the cube root of N (N^(1/3)), but don’t have any sort of library ready. Easy solution? Binary search! You know x=y^3, so “guess” a value for x, and go from there!


Q:You have eight balls all of the same size. 7 of them weigh the same, and one of them weighs slightly more. How can you fine the ball that is heavier by using a balance and only two weighings?


Q:How do you cut a rectangular cake into two equal pieces when someone has already taken a rectangular piece from it? The removed piece an be any size or at any place in the cake. You are only allowed one straight cut

Q:A software engineer has the capability of thinking 100 lines of code in five minutes and can type 100 lines of code in 10 minutes. He takes a break for five minutes after every ten minutes. How many lines of codes will he complete typing after an hour?

250 lines of code

Q:If 75 men can complete a piece of work in 20 days. How much longer will it take to complete the work by 50 men?

30 days.
Explanation:
With the 75 men case:
One day work = 1 / 20
One man’s one day work = 1 / ( 20 * 75)
Now with the 50 men case:
No. Of workers = 50
One day work = 50 * 1 / ( 20 * 75)

The total number of days required to complete the work = (75 * 20) / 50 = 30 days.


Q:An empty swimming pool can be filled to capacity through an inlet pipe in 3 hours, and it can be completely drained by a drainpipe in 6 hours. If both pipes are fully open at the same time, in how many hours will the empty pool be filled to capacity?

Wednesday, August 29, 2007

Generics in C#

With .NET 2.0 , C# now has generic methods, generic classes, generic structures and generic interfaces. But in addition, it also has generic delegates

The question might arise as to why it was desirable to introduce generics in C#. One reason is that creating data structures like Stacks, Queues, ArrayLists, Hashtables and SortLIsts requires boxing and unboxing of data because these constructs are defined in terms of the object data type. Therefore when other data types are used in these data structure, it is necessary to use type conversion, i.e. boxing and unboxing. One of the problems with this process is that if these actions are preformed a large number of times, then they can use a large amount of clock time doing these processes. Further if the boxing and unboxing is performed incorrectly, then errors can occur. However the errors are usually runtime errors rather than compile time errors making it therefore more difficult to find and to correct. Generics in C# reduce the need for boxing and unboxing. As a result, the clock time requirements are reduced. In addition, if there are any errors in using the data, they may be more easily found at compile time rather than at run time making the program much more type safe.



Builtin Generic Interfaces and Generic Classes


The namespace: System.Collections.Generic contains several useful interfaces. Because of the frequency of the expected use of generics in C# programs, the following using appears by default above program created by the IDE:



using System.Collections.Generic;




The following table lists some of the generic interfaces that are included in this namespace:


ICollection

IComparable

IComparer

IDictionary

IEnumerable

IEnumerator

IList




Note: T is frequently used for the unknown data type, K is used for the unknown key type and V is used for the unknown value type. If more than one unknown is required, then the letters: R and S are used.

Several of the generic interfaces listed above have non-generic interface counter parts that were discussed earlier in the lectures.

In addition to the generic interfaces listed above, C# has several generic classes built in as well. These classes are also included in the namespace: System.Collections.Generic. The following table lists some of these builtin generic classes as well as their non-generic counterparts:


Open table as spreadsheet Generic Class
NonGeneric Conterpart in System.Collection

Collection
CollectionBase

Comparer
Comparer

Dictionary
HashTable

List
ArrayList

LinkedList

Queue
Queue

SortedDictionary
SortedList

Stack
Stack




For example the generic class List above could be used to manage a list of any data type. Some of the methods for this class are:


Open table as spreadsheet Method
Purpose

Add()
Adds elements to the list

BinarySearch()
Locates a particular element in the list returning a position

Contains()
Determine if an element is in the list returning a bool

Remove()
Removes an element and returns a bool to indicate whether it was removed.

this[int index]
An indexer with {get; set;}




Suppose that you wanted to create a list of objects for the class: People. Using List, this could be done by the following definition:



List theCustomers = new List();




This List could therefore be managed as in the console program: CustomersList.cs. Notice how this program works similar to using an ArrayList.





Generic Methods




Generic Classes




Generic Class Inheritance from Classes and Interfaces

Explicit Interface Implementation

Suppose that theClass is derived from two different and unrelated interfaces: Interface1 and Interface2. Further suppose that each of these interfaces has a method: theMethod() with the same signature. The question is how to define theClass so that each theMethod() is implemented. To do this requires what is called an explicit implementation. An explicit implementation requires that at least one of the implemented methods of theClass has its name preceded with the name of the interface (which in this case is called an explicit implementation of the method). When this is done, the implemented method does not have an access specifier. An explicit implementation helps to distinguish which implementation is being used if there is more than one.

For example the two methods could be defined in the class as in the following:



theMethod()
{
....
}
Interface2.theMethod()
{
....
}




That is suppose the program contained the following code:



interface Interface1
{
void theFirstOne();
void theMethod();
}
interface Interface2
{
void theSecondOne();
void theMethod();
}
class theClass: Interface1, Interface2
{
. ........
public void theFirstOne()
{
.....
}
public void theSecondOne()
{
......
}

// The following will implement the Interface1 method
//
public void theMethod()
{
...
}
// The following will be an explicit implementation of
// the Interface2 method. Notice no access specifier.
//
Interface2.theMethod()
{
....
}
}




so that when defining an instance of theClass, as in the following:



theClass theObject = new theClass();




and then the call of theMethod() would be the following:



theObject.theMethod();




but this would be calling theMethod() that was derived from the interface: Interface1 without any additional explicit notation.

In order to access the explicit implementation: Interface2.theMethod() a reference to the interface: Interface2 must be declared as in the following:



Interface2 theReference = (Interface2) theObject;




Then, using theReference, the explicit implementation may be accessed as in the following:



theReference.theMethod();




For an example of this concept see: explicitImplimentation.cs

The example above only made one of theMethod() functions an explicit implementation. What may be desirable would be to make each an explicit implementation. Some authors on C# recommend that each method inherited from an interface be an explicit implementation. In this way there would be fewer problems when the code was modified by other programmers or if the code was in the component library with little or no documentation to warn about the problems that may be encountered deriving a class from the component interfaces.

Interface : Using the is and the as Operators

Some times it is not clear whether a reference to an interface does in fact have access to the class' object. This condition may be checked by using the is or the as operator. For example suppose that a program has a class: theClass and it is derived from the interface: Interface. Then the question is whether theReference of Interface can be used to access an object of theClass in the following:



theClass theClassReference = new theClass();
Interface theReference = (Interface) theClassReference;




Further suppose that theClass has a method: theMethod(). What is desired is whether:



theReference.theMethod();




is syntactically correct. If it is not, then an exception of type: System.InvalidCastException is thrown. (More will be said about exceptions in a later lecture.)

To prevent this exception from occurring, this relationship could be tested prior to implementing the type casting and the call of the method: theMethod() by theReference using the following code:



if((theClassReference is Interface)
{
Interface theReference = (Interface) theClassReference;
theReference.theMethod();
}




As a result of the above, theReference would only call theMethod() should theClass have implemented the interface: Interface.

The operator as works similar to is. Using as, the above could be implemented in the following manner:



theClassReference = new theClass();
Interface theReference = theClassReference as Interface;
if(theReference != null)
theReference.theMethod();




In this if( ) statement theReference would be null should it not represent the object of theClass to which theClassReference refers.
// program_id overrideInterface.cs
// description This program demonstrates a class
// derived from a class that overrides
// the base class' implementation
// of the interface's method.
//

using System;

namespace theChecking
{
interface IAccounts
{
decimal theBalance {set; get;}
void Deposit(decimal theAmount);

void Withdrawal(decimal theAmount);
}

interface IFee: IAccounts
{
decimal theFee {get; set;}
void CalculateFee();
}

class Checking: IFee
{
private decimal Fee;
public decimal theFee
{
get
{
return Fee;
}
set
{

Fee = value;
}
}

private decimal Balance;
public decimal theBalance
{
get
{
return Balance;
}
set
{
Balance = value;
}
}
public Checking()
{
Balance = 0.00M;
}
public void Deposit(decimal theAmount)
{
Balance += theAmount;
}
public void Withdrawal(decimal theAmount)
{
Balance -= theAmount;
}
public virtual void CalculateFee()
{
Balance -= Fee;
}
}
class Savings : Checking
{
public override void CalculateFee()
{
theBalance *= (1 + theFee);
}
public decimal ShowInterest()
{
return (theBalance * theFee);
}

}
class theProgram
{
static void Main()
{

Checking checkingAccount = new Checking();

Savings savingsAccount = new Savings();

Console.Clear();

Console.Write("What is the checking account fee? ");
checkingAccount.theFee = Decimal.Parse(Console.ReadLine());

Console.Write("\nWhat was the checking account deposits? ");
checkingAccount.Deposit(Decimal.Parse(Console.ReadLine()));

Console.Write("What was the checking account withdrawals? ");
checkingAccount.Withdrawal(Decimal.Parse(Console.ReadLine()));


if(checkingAccount.theBalance <= 500.00m)
{
checkingAccount.CalculateFee();
Console.WriteLine("\nThe checking account was charged a fee of {0:c}",
checkingAccount.theFee);
}

Console.WriteLine("\nCurrent balance of the checking account is {0:c}.",
checkingAccount.theBalance);

Console.Write("\n\nWhat is the savings account interest rate? ");
savingsAccount.theFee = Decimal.Parse(Console.ReadLine())/100;

Console.Write("\nWhat was the savings account deposits? ");
savingsAccount.Deposit(Decimal.Parse(Console.ReadLine()));

Console.Write("What was the savings account withdrawals? ");
savingsAccount.Withdrawal(Decimal.Parse(Console.ReadLine()));

if(savingsAccount.theBalance >= 500.00m)

{
Console.WriteLine("\nThe savings account was awarded an interest fee of {0:c}",
savingsAccount.ShowInterest());
savingsAccount.CalculateFee();
}
Console.WriteLine("\nCurrent balance of the savings account is {0:c}.",
savingsAccount.theBalance);

Console.WriteLine("\n\n");
Console.ReadKey();
}

}
}

Virtual Methods in C#

Earlier in the notes, an example: inheritance5.cs was shown where both the base class and the derived class both have methods with the same name and signature. As was seen, this was permitted by the compiler but a warning error was issued. To overcome this warning error, the modifier new was used in the example: inheritance3.cs on the derived class' method to inform the compiler that the definition of the derived class' method was hiding the base class' method. This example also compiled and ran but there were no warning errors.

Sometimes it is desirable to force the derived class to either use the base class' method or to override the base class' method with an entirely different method but with the same name. In either case the base class' method must have the modifier: virtual. When this modifier is used, then the modifier new may not be used. Instead the modifier override must be used if the derived class is to have a method with the same name as the base class. To see an example where the base class is using the modifier virtual but the derived class does not use these names see: inheritance7.cs. To see an example where the base class uses the modifier virtual and the derived class defines methods with the same name by using the modifier: override see: inheritance6.cs. Recall how when the ToString() method was discussed in a previous section, that the modifier override was used. The reason for this is that the method ToString() is a virtual method of the class: System.Object.


// program_id inheritance1.cs
// written?_by don voils
// date_written 12/11/2006
// description This program demonstrates how
// to use inheritance.
//

using System;

class theProgram
{
public class Customer
{
private string CustomerID;
private string CustomerName;
private string CustomerAddress;
private string CustomerCity;
private string CustomerState;
private string CustomerZipCode;

public void setCustomerID(string ID)
{
CustomerID = ID;
}
public void setCustomerName(string Name)
{
CustomerName = Name;
}
public void setCustomerAddress(string Address)
{
CustomerAddress = Address;
}
public void setCustomerCity(string City)
{
CustomerCity = City;
}
public void setCustomerState(string State)
{

CustomerState = State;
}
public void setCustomerZipCode(string Code)
{
CustomerZipCode = Code;
}
public string getCustomerID()
{
return CustomerID;
}
public string getCustomerName()
{
return CustomerName;
}
public string getCustomerAddress()
{
return CustomerAddress;
}
public string getCustomerCity()
{
return CustomerCity;
}
public string getCustomerState()
{
return CustomerState;
}
public string getCustomerZipCode()
{
return CustomerZipCode;
}
}

public class Invoice : Customer
{
private decimal InvoiceAmount;

public void setInvoiceAmount(decimal Amount)
{
InvoiceAmount = Amount;
}
public decimal getInvoiceAmount()
{
return InvoiceAmount;

}
}
static void Main()
{
Invoice theTransaction = new Invoice();
Console.Write("What is the customer's ID? ");
theTransaction.setCustomerID(Console.ReadLine());

Console.Write("What is the customer's name? ");
theTransaction.setCustomerName(Console.ReadLine());

Console.Write("What is the customer's address? ");
theTransaction.setCustomerAddress(Console.ReadLine());

Console.Write("What is the customer's city? ");
theTransaction.setCustomerCity(Console.ReadLine());

Console.Write("What is the customer's state? ");
theTransaction.setCustomerState(Console.ReadLine());

Console.Write("What is the customer's zip code? ");
theTransaction.setCustomerZipCode(Console.ReadLine());

Console.Write("What is the amount of the invoice? ");
theTransaction.setInvoiceAmount(Decimal.Parse(Console.ReadLine()));

Console.Clear();

Console.WriteLine("Customer ID: {0}", theTransaction.getCustomerID());
Console.WriteLine("Customer Name: {0}", theTransaction.getCustomerName());
Console.WriteLine("Customer Address: {0}", theTransaction.getCustomerAddress());
Console.WriteLine("Customer City: {0}", theTransaction.getCustomerCity());
Console.WriteLine("Customer State: {0}", theTransaction.getCustomerState());
Console.WriteLine("Customer Zip Code: {0}", theTransaction.getCustomerZipCode());
Console.WriteLine("Invoice Amount: {0,15:c}\n\n", theTransaction.getInvoiceAmount());
Console.ReadKey();
}


}



// program_id inheritance2.cs
// written?_by don voils
// date_written 12/11/2006
// description This program demonstrates how
// to use inheritance.
//

using System;

class theProgram
{
public class People
{
private string PeopleID;
private string PeopleName;
private string PeopleAddress;
private string PeopleCity;
private string PeopleState;
private string PeopleZipCode;

public void setPeopleID(string ID)
{
PeopleID = ID;
}
public void setPeopleName(string Name)
{
PeopleName = Name;
}
public void setPeopleAddress(string Address)
{
PeopleAddress = Address;
}
public void setPeopleCity(string City)
{
PeopleCity = City;
}
public void setPeopleState(string State)
{

PeopleState = State;
}
public void setPeopleZipCode(string Code)
{
PeopleZipCode = Code;
}
public string getPeopleID()
{
return PeopleID;
}
public string getPeopleName()
{
return PeopleName;
}
public string getPeopleAddress()
{
return PeopleAddress;
}
public string getPeopleCity()
{
return PeopleCity;
}
public string getPeopleState()
{
return PeopleState;
}
public string getPeopleZipCode()
{
return PeopleZipCode;
}
}
public class Employee : People
{
private char PayType;
private decimal PayRate;
private decimal GrossPay;
public void setPayType(char Type)
{
PayType = Type;
}
public char getPayType()
{
return PayType;

}
public void setPayRate(decimal Rate)
{
PayRate = Rate;
}
public decimal getPayRate()
{
return PayRate;
}
public void setGrossPay(decimal Amount)
{
GrossPay = Amount;
}
public decimal getGrossPay()
{
return GrossPay;
}
}
public class Customer : People
{
private decimal BalancetDue;

public void setBalanceDue(decimal Amount)
{
BalancetDue = Amount;
}
public decimal getBalanceDue()
{
return BalancetDue;
}
}
public class Vendor : People
{
private decimal AmountOwed;

public void setAmountOwed(decimal Amount)
{
AmountOwed = Amount;
}
public decimal getAmountOwed()
{
return AmountOwed;
}

}
static void Main()
{
bool processAgain = true;
while (processAgain == true)
{
Console.WriteLine(" Account Type\n");
Console.WriteLine(" 1. Employee");
Console.WriteLine(" 2. Customer");
Console.WriteLine(" 3. Vendor");
Console.Write("\n Which? ");
char TransactionType = Char.Parse(Console.ReadLine());
Console.Clear();
switch (TransactionType)
{
case '1':
processEmployee();
break;
case '2':
processCustomer();
break;
case '3':
processVendor();
break;
default:
Console.WriteLine("You selected an incorrect type." +
"Please try again.\n");
break;
}
Console.Write("\nDo you want to process another? Y or N ");
TransactionType = Char.Parse(Console.ReadLine());
Console.Clear();
if ((TransactionType != 'y') && (TransactionType != 'Y'))
processAgain = false;
else
processAgain = true;
}
}

static void processEmployee()
{
Employee theTransaction = new Employee();
Console.Write("What is the employee's ID? ");

theTransaction.setPeopleID(Console.ReadLine());

Console.Write("What is the employee's name? ");
theTransaction.setPeopleName(Console.ReadLine());

Console.Write("What is the employee's address? ");
theTransaction.setPeopleAddress(Console.ReadLine());

Console.Write("What is the employee's city? ");
theTransaction.setPeopleCity(Console.ReadLine());

Console.Write("What is the employee's state? ");
theTransaction.setPeopleState(Console.ReadLine());

Console.Write("What is the employee's zip code? ");
theTransaction.setPeopleZipCode(Console.ReadLine());

char theType;
do
{
Console.Write("What is the employee's pay type (H:Hourly or S:Salaried? ");
theType = Char.Parse(Console.ReadLine());
} while ((theType != 'H') && (theType != 'h') && (theType != 'S') && (theType != 's'));
theTransaction.setPayType(theType);

Console.Write("What is the employee's pay rate? ");
theTransaction.setPayRate(Decimal.Parse(Console.ReadLine()));

Console.Write("What is the employee's gross pay? ");
theTransaction.setGrossPay(Decimal.Parse(Console.ReadLine()));
Console.WriteLine("\n\n");

Console.Clear();
Console.WriteLine("Employee ID: {0}", theTransaction.getPeopleID());
Console.WriteLine("Employee Name: {0}", theTransaction.getPeopleName());
Console.WriteLine("Employee Address: {0}", theTransaction.getPeopleAddress());
Console.WriteLine("Employee City: {0}", theTransaction.getPeopleCity());
Console.WriteLine("Employee State: {0}", theTransaction.getPeopleState());
Console.WriteLine("Employee Zip Code: {0}", theTransaction.getPeopleZipCode());
Console.WriteLine("Employee Pay Type: {0}", theTransaction.getPayType());
Console.WriteLine("Employee Pay Rate: {0,15:c}", theTransaction.getPayRate());
Console.WriteLine("Employee Gross Pay: {0,15:c}", theTransaction.getGrossPay());
Console.WriteLine("\n\n");

}

static void processCustomer()
{
Customer theTransaction = new Customer();
Console.Write("What is the customer's ID? ");
theTransaction.setPeopleID(Console.ReadLine());

Console.Write("What is the customer's name? ");
theTransaction.setPeopleName(Console.ReadLine());

Console.Write("What is the customer's address? ");
theTransaction.setPeopleAddress(Console.ReadLine());

Console.Write("What is the customer's city? ");
theTransaction.setPeopleCity(Console.ReadLine());

Console.Write("What is the customer's state? ");
theTransaction.setPeopleState(Console.ReadLine());

Console.Write("What is the customer's zip code? ");
theTransaction.setPeopleZipCode(Console.ReadLine());

Console.Write("What is the cutomer's balance due? ");
theTransaction.setBalanceDue(Decimal.Parse(Console.ReadLine()));
Console.WriteLine("\n\n");

Console.Clear();
Console.WriteLine("Customer ID: {0}", theTransaction.getPeopleID());
Console.WriteLine("Customer Name: {0}", theTransaction.getPeopleName());
Console.WriteLine("Customer Address: {0}", theTransaction.getPeopleAddress());
Console.WriteLine("Customer City: {0}", theTransaction.getPeopleCity());
Console.WriteLine("Customer State: {0}", theTransaction.getPeopleState());
Console.WriteLine("Customer Zip Code: {0}", theTransaction.getPeopleZipCode());
Console.WriteLine("Cusomter Balance Due: {0,15:c}", theTransaction.getBalanceDue());
Console.WriteLine("\n\n");
}


static void processVendor()
{
Vendor theTransaction = new Vendor();
Console.Write("What is the vendor's ID? ");

theTransaction.setPeopleID(Console.ReadLine());

Console.Write("What is the vendor's name? ");
theTransaction.setPeopleName(Console.ReadLine());

Console.Write("What is the vendor's address? ");
theTransaction.setPeopleAddress(Console.ReadLine());

Console.Write("What is the vendor's city? ");
theTransaction.setPeopleCity(Console.ReadLine());

Console.Write("What is the vendor's state? ");
theTransaction.setPeopleState(Console.ReadLine());

Console.Write("What is the vendor's zip code? ");
theTransaction.setPeopleZipCode(Console.ReadLine());

Console.Write("What is the amount owed the vendor? ");
theTransaction.setAmountOwed(Decimal.Parse(Console.ReadLine()));
Console.WriteLine("\n\n");

Console.Clear();
Console.WriteLine("Vendor ID: {0}", theTransaction.getPeopleID());
Console.WriteLine("Vendor Name: {0}", theTransaction.getPeopleName());
Console.WriteLine("Vendor Address: {0}", theTransaction.getPeopleAddress());
Console.WriteLine("Vendor City: {0}", theTransaction.getPeopleCity());
Console.WriteLine("Vendor State: {0}", theTransaction.getPeopleState());
Console.WriteLine("Vendor Zip Code: {0}", theTransaction.getPeopleZipCode());
Console.WriteLine("Amount Owed: {0,15:c}", theTransaction.getAmountOwed());
Console.WriteLine("\n\n");
}
}



// program_id inheritance3.cs
// written_by don voils
// date_written 10/2/2006
// description In this example the base class has a
// protected attribute that is accessible
// in the derived class. In addition the
// derived class has methods with the
// same name as the base class and overcomes
// this restriction by using the keyword word: new.
//

using System;

namespace constructor
{
class stuff
{
protected int member;

public void setMember(int a)
{
member = a;
Console.WriteLine("Through the stuff class using the setMember() method.\n");
}

public void print()
{
Console.WriteLine("Through the stuff class using the print() method: member = {0}.\n", member);
}
}

class stuff1 : stuff
{
public new void setMember(int a)
{
member = a;
Console.WriteLine("Through the class stuff1 using the setMember() method.\n");
}

public new void print()
{
Console.WriteLine("Through the class stuff1 using the print() method: member = {0}.\n", member);
}
}

class myProgram
{
static void Main()
{
Console.WriteLine("Defining theObject an object of the class stuff.\n");

stuff theObject = new stuff();

theObject.setMember(10);

theObject.print();

Console.WriteLine("\n\n");

Console.WriteLine("Defining object1 an object of the class stuff1.\n");

stuff1 object1 = new stuff1();

object1.setMember(15);

object1.print();

Console.WriteLine("\n\n");
Console.ReadKey();
}
}
}



// program_id inheritance4.cs
// written?_by don voils
// date_written 12/11/2006
// description This program demonstrates how
// to prevent inheritance. The program is
// the same as inheritance1.cs except
// the class Customer is sealed. The
// program inheritance1.cs compiled and
// ran but this program will not.
//

using System;

class theProgram
{
sealed public class Customer
{
private string CustomerID;
private string CustomerName;
private string CustomerAddress;
private string CustomerCity;
private string CustomerState;
private string CustomerZipCode;

public void setCustomerID(string ID)
{
CustomerID = ID;
}
public void setCustomerName(string Name)
{
CustomerName = Name;
}
public void setCustomerAddress(string Address)
{
CustomerAddress = Address;
}
public void setCustomerCity(string City)
{

CustomerCity = City;
}
public void setCustomerState(string State)
{
CustomerState = State;
}
public void setCustomerZipCode(string Code)
{
CustomerZipCode = Code;
}
public string getCustomerID()
{
return CustomerID;
}
public string getCustomerName()
{
return CustomerName;
}
public string getCustomerAddress()
{
return CustomerAddress;
}
public string getCustomerCity()
{
return CustomerCity;
}
public string getCustomerState()
{
return CustomerState;
}
public string getCustomerZipCode()
{
return CustomerZipCode;
}
}

public class Invoice : Customer
{
private decimal InvoiceAmount;

public void setInvoiceAmount(decimal Amount)
{
InvoiceAmount = Amount;

}
public decimal getInvoiceAmount()
{
return InvoiceAmount;
}
}
static void Main()
{
Invoice theTransaction = new Invoice();
Console.Write("What is the customer's ID? ");
theTransaction.setCustomerID(Console.ReadLine());

Console.Write("What is the customer's name? ");
theTransaction.setCustomerName(Console.ReadLine());

Console.Write("What is the customer's address? ");
theTransaction.setCustomerAddress(Console.ReadLine());

Console.Write("What is the customer's city? ");
theTransaction.setCustomerCity(Console.ReadLine());

Console.Write("What is the customer's state? ");
theTransaction.setCustomerState(Console.ReadLine());

Console.Write("What is the customer's zip code? ");
theTransaction.setCustomerZipCode(Console.ReadLine());

Console.Write("What is the amount of the invoice? ");
theTransaction.setInvoiceAmount(Decimal.Parse(Console.ReadLine()));

Console.Clear();

Console.WriteLine("Customer ID: {0}", theTransaction.getCustomerID());
Console.WriteLine("Customer Name: {0}", theTransaction.getCustomerName());
Console.WriteLine("Customer Address: {0}", theTransaction.getCustomerAddress());
Console.WriteLine("Customer City: {0}", theTransaction.getCustomerCity());
Console.WriteLine("Customer State: {0}", theTransaction.getCustomerState());
Console.WriteLine("Customer Zip Code: {0}", theTransaction.getCustomerZipCode());
Console.WriteLine("Invoice Amount: {0,15:c}", theTransaction.getInvoiceAmount());
Console.WriteLine("\n\n");
}

}



// program_id inheritance5.cs
// written_by don voils
// date_written 10/2/2006
// description This example is contains two class
// one of which is derived from the other.
// The base class and the derived class contain
// methods with the same name. While the program
// compiles and runs, it contains several warning
// error notifying the programmer that the two
// classes have methods with the same names.
//

using System;

namespace constructor
{
class stuff
{
protected int member;

public void setMember(int a)
{
member = a;
Console.WriteLine("Through the stuff class using the setMember() method.\n");
}

public void print()
{
Console.WriteLine("Through the stuff class using the print() method: member = {0}.\n"
, member);
}
}

class stuff1 : stuff
{
// has the same name as a method in the base class.
//
public void setMember(int a)

{
member = a;
Console.WriteLine("Through the class stuff1 using the setMember() method.\n");
}

// has the same name as a method in the base class.
public void print()
{
Console.WriteLine("Through the class stuff1 using the print() method: member = {0}.\n",
member);
}
}

class myProgram
{
static void Main()
{
Console.WriteLine("Defining theObject an object of the class stuff.\n");

stuff theObject = new stuff();

theObject.setMember(10);

theObject.print();

Console.WriteLine("\n\n");

Console.WriteLine("Defining object1 an object of the class stuff1.\n");

stuff1 object1 = new stuff1();

object1.setMember(15);

object1.print();

Console.WriteLine("\n\n");
Console.ReadKey();
}
}
}



// program_id inheritance6.cs
// written_by don voils
// date_written 10/2/2006
// description In this example the base class has a
// protected attribute that is accessible
// in the derived class.
//
// In addition the derived class has methods with the
// same name as the base class. This overcomes
// this restriction by using the keyword words: virtual
// in the base class and overridden in the derived class.
//

using System;

namespace theProgram
{
class theBase
{
protected int member;

virtual public void setMember(int a)
{
member = a;
Console.WriteLine("Through the theBase class using the setMember() method.\n");
}

virtual public void print()
{
Console.WriteLine("Through the theBase class using the print() method: member = {0}.\n", member);
}
}

// Notice that the attribute member of theBase class was
// declared as protected, therefore it is accessible in the
// derived class as though it was a private attribute
// of the derived class.
//
class theDerived : theBase
{

override public void setMember(int a)
{
member = a;
Console.WriteLine("Through the class theDerived using setMember() method.\n");
}

override public void print()
{
Console.WriteLine("Through the class theDerived using print() method: member = {0}.\n", member);
}
}

class myProgram
{
static void Main()
{
Console.WriteLine("Defining theBaseObject an object of the class theBase.\n");

theBase theBaseObject = new theBase();

theBaseObject.setMember(10);

theBaseObject.print();

Console.WriteLine("\n\n");

Console.WriteLine("Defining theDerivedObject an object of the class theDerived.\n");

theDerived theDerivedObject = new theDerived();

theDerivedObject.setMember(15);

theDerivedObject.print();

Console.WriteLine("\n\n");
Console.ReadKey();
}
}
}



// program_id inheritance7.cs
// written_by don voils
// date_written 10/2/2006
// description In this example the base class has a
// methods that are declared as virtual.
// The derived class does not have methods
// by these names. However the program
// compiles and runs.
//

using System;

namespace theProgram
{
class theBase
{
protected int member;

virtual public void setMember(int a)
{
member = a;
Console.WriteLine("Through the theBase class using the setMember() method.\n");
}

virtual public void print()
{
Console.WriteLine("Through the theBase class using the print() method: member = {0}.\n", member);
}
}

class theDerived : theBase
{

}

class myProgram
{
static void Main()
{
Console.WriteLine("Defining theBaseObject an object of the class theBase.\n");

theBase theBaseObject = new theBase();

theBaseObject.setMember(10);

theBaseObject.print();

Console.WriteLine("\n\n");

Console.WriteLine("Defining theDerivedObject an object of the class theDerived.\n");

theDerived theDerivedObject = new theDerived();

theDerivedObject.setMember(15);

theDerivedObject.print();

Console.WriteLine("\n\n");
Console.ReadKey();
}
}
}

Base n Derived Class references : C#

References to a Base Class Manipulate Objects of the Derived Class
Polymorphism in C# is slightly different from that in C++. As you may recall, in C++ part of the polymorphism feature used pointers and part of it used references. Since C# does not use pointers but does use references, only the reference part is used.

For example, references to a base class may be used to reference a derived class' object. In this way, an object of a derived class may be treated as an object of the base class.

For example suppose a program has two classes: theBase and theDerived where theDerived is derived from theBase. Suppose the following definition of a reference of the derived class:



theDerived theDerivedReference = new theDerived();




With the following definition, the reference: theBaseReference references the derived object referenced by theDerivedReference.



theBase theBaseReference = theDerivedReference;




This last statement would then permit theBaseReference to manipulate the theBase class' contents of the object to which theDerivedRefence refers to.

For excample see theReference1.cs. One of the problems with this relationship is similar to the problem with pointers in C++. That is the reference: theBaseReference may only refer to the base class members of the derived class object. It can not refer to the derived class members of the object. Notice in this program where theBaseReference is trying to access the method: show_theDerived() if the comment symbols are removed, the program will not compile.

The reverse relationship is not possible. Meaning, that a reference to a derived class may not be used with an object of the base class. If a program does, then there will be a compiler error. For example if the following code replaced the code in the previous example the program would not compile:t



theBase theBaseReference = new theBase(2);
theDerived theDerivedReference;

theDerivedReference = theBaseReference;




See theReference3.cs.

In addition if anotherDerived is a class that is itself derived from theDerived class, then theBaseReference may also be used to access theBase class' part of an object of anotherDerived class' object. For example see theReference2.cs.


// program_id theReference1.cs
// written by don voils
// date_written 10/3/2006
// Descriptioin The program shows how references to a base
// class can be used to access the base class
// part of an object of the derived class.
//

using System;

class theProgram
{
public class theBase
{
private short theBaseMember;
public theBase(short theShort)
{
theBaseMember = theShort;
}
public short show_theBase()
{
return theBaseMember;
}
}

public class theDerived : theBase
{
private short theDerivedMember;
public theDerived(short firstShort, short secondShort)
: base(firstShort)
{
theDerivedMember = secondShort;
}
public short show_theDerived()
{
return theDerivedMember;
}
}

static void Main()
{

theBase theBaseReference;
theDerived theDerivedReference = new theDerived(1, 2);

theBaseReference = theDerivedReference;

Console.WriteLine("The value of theBaseMember is {0}.\n",
theBaseReference.show_theBase());

//
// The following line will not compile. Why?
//
// Console.WriteLine("The value of theDerivedMember is {0}.\n",
// theBaseReference.show_theDerived());

Console.WriteLine("\n\n");
Console.ReadKey();
}


}



// program_id theReference2.cs
// written by don voils
// date_written 10/3/2006
// Descriptioin The program shows how references to a base
// class can be used to access the base class
// part of an object of a class that is derived from a
// class that is derived from the base.
//

using System;

class theProgram
{
public class theBase
{
private short theBaseMember;
public theBase(short theShort)
{
theBaseMember = theShort;
}
public short show_theBase()
{
return theBaseMember;
}
}

public class theDerived : theBase
{
private short theDerivedMember;
public theDerived(short firstShort, short secondShort)
: base(firstShort)
{
theDerivedMember = secondShort;
}
public short show_theDerived()
{
return theDerivedMember;
}

}

public class anotherDerived : theDerived
{
private short anotherDerivedMember;
public anotherDerived(short firstShort, short secondShort, short thirdShort)
: base(firstShort, secondShort)
{
anotherDerivedMember = thirdShort;
}
public short show_anotherDerived()
{
return anotherDerivedMember;
}
}

static void Main()
{
theBase theBaseReference;
theDerived theDerivedReference = new theDerived(1, 2);

theBaseReference = theDerivedReference;

Console.WriteLine("The value of theBaseMember is {0}.\n",
theBaseReference.show_theBase());

anotherDerived anotherDerivedReference = new anotherDerived(5, 6, 7);

theBaseReference = anotherDerivedReference;

Console.WriteLine("The value of theBaseMember is {0}.\n\n",
theBaseReference.show_theBase());

Console.ReadKey();
}


}



// program_id theReference3.cs
// written by don voils
// date_written 10/3/2006
// Descriptioin The program shows that a reference to
// a derived class may not be used to reference
// a base class object.
//

using System;

class theProgram
{
public class theBase
{
private short theBaseMember;
public theBase(short theShort)
{
theBaseMember = theShort;
}
public short show_theBase()
{
return theBaseMember;
}
}

public class theDerived : theBase
{
private short theDerivedMember;
public theDerived(short firstShort, short secondShort)
: base(firstShort)
{
theDerivedMember = secondShort;
}
public short show_theDerived()
{
return theDerivedMember;
}
}

static void Main()
{
theBase theBaseReference = new theBase(2);
theDerived theDerivedReference;

theDerivedReference = theBaseReference;

Console.WriteLine("\n\n");
Console.ReadKey();
}


}

Abstract in C# 2005

Abstract Classes and Methods
Two additional features of the C# polymorphism are abstract methods and abstract classes.

To define an abstract method the keyword: abstract must be placed in front of the method's definition and the abstract method can have no body as in the following code:



abstract public void theMethod();




In the case of classes, the keyword: abstract must appear before the word class in the definition of the class as in the following code:



abstract public class theClass
{
....
}




An abstract class must contain one or more abstract methods. Any class that contains an abstract method must be defined as an abstract class. An abstract class may not have any defined objects. In addition to the abstract methods, an abstract class may also have non abstract methods as well.

Abstract classes and methods must be defined public.

Any derived class of an abstract class must override the inherited abstract methods in order to permit the derived objects to be defined. If the abstract methods are not overridden, then the derived class would be considered abstract and any attempts to define objects for such a derived class would fail. As discussed above, this is done by placing the word override in front of the method's definition. For example see theAbstract1.cs.

While a class derived from an abstract class must implement each abstract method of the abstract class by overriding it, this is not true if a class is in turn derived from this derived class. For example see theAbstract2.cs.

One of the purposes of abstract classes is to provide a base from which other classes may be derived that in turn override the abstract methods. A second purpose is to permit the references of the abstract class to access the overridden methods as if they were references of the derived classes. For example see theAbstract3.cs.



// program_id theAbstract1.cs
// written by don voils
// date_written 10/3/2006
// Descriptioin The program shows how an abstract
// class and method can be defined as
// well as how to derive a class from the
// abstract class. If the keyword: override
// is removed from the definition of the
// method show() in the derived class,
// the program will not compile.
//

using System;

class theProgram
{
abstract public class theBase
{
private short theBaseMember;
public theBase(short theShort)
{
theBaseMember = theShort;
}
abstract public short show();
}

public class theDerived : theBase
{
private short theDerivedMember;
public theDerived(short firstShort, short secondShort)
: base(firstShort)
{
theDerivedMember = secondShort;
}
override public short show()
{
return theDerivedMember;
}

}

static void Main()
{
theDerived theDerivedReference = new theDerived(1, 2);

Console.WriteLine("The value of theBaseMember is {0}.\n\n",
theDerivedReference.show());

Console.ReadKey();
}


}



// program_id theAbstract2.cs
// written by don voils
// date_written 10/3/2006
// Descriptioin This program shows how an abstract
// class and method can be defined as
// well as how to derive a class from a class
// that is derived from an abstract class.
// In this case, this second derived class
// does not have to override the base class'
// abstract method.
//

using System;

class theProgram
{
abstract public class theBase
{
private short theBaseMember;
public theBase(short theShort)
{
theBaseMember = theShort;
}
abstract public short show();
}

public class theDerived : theBase
{
private short theDerivedMember;
public theDerived(short firstShort, short secondShort): base(firstShort)
{
theDerivedMember = secondShort;
}
override public short show()
{
return theDerivedMember;
}
}

public class nextDerived : theDerived
{
private short theNextDerivedMember;

public nextDerived(short firstShort, short secondShort, short thirdShort)
: base(firstShort, secondShort)
{
theNextDerivedMember = thirdShort;
}
public short showNextDerived()
{
return theNextDerivedMember;
}
}

static void Main()
{
nextDerived theReference = new nextDerived(1, 2, 3);

Console.WriteLine("The value of theNextDerivedMember is {0}.\n\n",
theReference.show());

Console.ReadKey();
}


}



// program_id theAbstract3.cs
// written by don voils
// date_written 10/3/2006
// Descriptioin This program shows how an abstract
// class and method can be defined as
// well as how to derive a class from a class
// that is derived from an abstract class.
// In this case, a second derived class
// is derived from the first derived class.
// In this program a reference to the abstract
// base class is used to access methods of
// each of the derived classes as if it was
// a reference to the respecitive classes.
// Without this base class being abstract,
// this reference would have been forced to
// access the base class' method which would
// have been impossible because it is in turn
// abstract.
//

using System;

class theProgram
{
abstract public class theBase
{
private short theBaseMember;
public theBase(short theShort)
{
theBaseMember = theShort;
}
abstract public short show();
}

public class theDerived : theBase
{
private short theDerivedMember;
public theDerived(short firstShort, short secondShort) : base(firstShort)

{
theDerivedMember = secondShort;
}
override public short show()
{
return theDerivedMember;
}
}

public class nextDerived : theDerived
{
private short theNextDerivedMember;

public nextDerived(short firstShort, short secondShort, short thirdShort)
: base(firstShort, secondShort)
{
theNextDerivedMember = thirdShort;
}
override public short show()
{
return theNextDerivedMember;
}
}

static void Main()
{

theDerived theDerivedReference = new theDerived(4, 5);

theBase theBaseReference = theDerivedReference;

Console.WriteLine("The value of theDerivedMember is {0}.\n",
theBaseReference.show());

nextDerived theNextDerivedReference = new nextDerived(1, 2, 3);

theBaseReference = theNextDerivedReference;

Console.WriteLine("The value of theNextDerivedMember is {0}.\n\n",
theBaseReference.show());

Console.ReadKey();
}

}

Thursday, June 07, 2007

Can a developer become software architect?"

Software Architecture: Past, Present and Future
by Diego Dagum
What exactly is software architecture? Do we really need it? Why have we only recently been discussing it? Has some contagious fever suddenly infected those who claim to be architects? And who are these people anyway? Are they gurus, senior developers, or maybe just smooth-talking self-promoters?
These are questions that junior and senior developers are asking about software architecture and software architects. This article will address these questions and more, asking the forbidden question: "Can a developer become software architect?"
The Need for Software Architecture
Not so long ago, programming platforms were more self-contained. From robust and complex environments like mainframe COBOL to light and easy-to-understand xBase languages, the most important technical decisions were already taken. For software projects, that meant both benefits and drawbacks. A benefit, because where a decision exists, no time needs to be spent in discussions about the best way to do anything.
In non-enterprise environments (academics, small business), this solution model was adequate and successful for a long time. But it had drawbacks at the enterprise level, because there was one notorious downfall - "all-or-nothing" platforms were too rigid to adapt to the competitive, highly changeable environments required by a global economy. Also, during mergers and acquisitions, it's really hard to get two independent platforms to play well together.
Thus, component-oriented software was born with the goal of a new agility in scaling applications. Now we could choose among a broad set of platforms to produce modular pieces (or components) ready to be used by other components that were either made by us or by vendors. Once established that integration was not an issue, component orientation gained in popularity in the enterprise, where the technical decision makers became free to use the best platform and tools as solutions for specific problems, rather than be constrained to a specific platform as before. However, soon it became apparent that there was a need to plan and manage components to ensure success.Defining Software ArchitectureSo, thanks to component-oriented software we could choose the platform which best fit a specific problem. Despite that, the paradigm shift of new platforms was difficult for many developers to learn. Thus, one of the first objectives of good architecture was to gently hide the complexity of new platforms and APIs behind easily understandable ones which were more focused in the context of the problem being solved (typically a business problem).
In that way, software architecture became a highway to develop business solutions in a timely, secure, and accurate manner. Under the pavement of that highway we still have pre-made technical decisions that architects had to take to make the developers' tasks easier.
The difference from past platforms is that now, rather than buying necessarily restrictive general-purpose software from a vendor, an organization's members can make their own decisions regarding the function of the business solution to be developed. This means we need to have this decision making ability in house. It means a new role, the Software Architect.What Software Architecture Used To Be
Software architecture emerged from a bundle of practices applied by senior developers. Some of these merit mention:
Design Patterns. This all started with a book simply called "Design Patterns" that is still a best-seller. These patterns cover highly decoupled, reusable solutions for frequent problems about responsibility assignment in object-oriented programming (OOP). Actually, they merely solve these problems on a small scale, but surely this book sowed the seeds for a new way of thinking about applications, constituting the DNA of several enterprise systems. We suggest as a reading the article "Last Call to Design Patterns".
Architecture Patterns. In the days of Smaltalk, one pattern proposed an extraordinary way of decoupling user experience from persistence mechanisms. This pattern, the Model-View-Controller (MVC), granted the responsibility of user interaction handling to a component which played a role known as the "View". The "Model" component had the responsibility of keeping the business model state consistent. A third component, called the "Controller" interpreted events originated from the View, promoting changes in the Model state accordingly. This pattern permitted interchanging components of any role very inexpensively, thus enabling multi-channel applications (that is, applications available in a vast variety of platforms and contexts). Think beyond the typical dichotomy of client versus server. Think of ATMs, mobile phones, and other platforms. We have just to re-implement the View component in these use cases ("Bill payment," "Book service," and so on). The same applies to the Model. It is not just a discussion about Oracle versus SQL Server versus IBM DB/2 versus MySQL versus whichever. Think also of legacy mainframe environments versus XML files for smaller data repositories (useful to easily mount development environments where the whole infrastructure could not be present). This pattern brought not just execution distribution but development distribution. Development could be better organized in different teams working in an asynchronous manner thanks to the inherent decoupling capabilities of this pattern. Click here to read n discussion of this pattern.MVC was just the beginning of patterns. Since the mid-nineties a series of books classified and organized many other architecture patterns. We recommend the Patterns of Software Architecture (POSA) books, Sun's Core J2EE Patterns, Martin Fowler's series, and -- with the launch of .NET -- the MS Patterns and Practices guides (which include an interesting, ready-to-use set of application blocks, see Frameworks, below.) For more information visit the Patterns and Practices Center.
Anti-patterns. A counter-concept grew in parallel with the concept of patterns. If a pattern is a best practice, an anti-pattern is a worst one. There is an infamous common anti-pattern, which aspiring architects and junior ones apply all the time: that of over architecting every software component. This is commonly expressed by immediately adopting the newest version of everything without actually considering if it is beneficial. Perhaps this is done with the misconception that doing so will provide a comprehensive, easy-to-change architecture in some near future. But experience is showing that the opposite is happening; nobody wants to touch unnecessarily complex solutions, so they remain "as is" until they are completely replaced. Click here for a discussion about this.
Frameworks. In a remarkable effort to enable largescale software production, a variety of component blocks (better known as frameworks) appeared. There are frameworks to solve the gap between the domain object model and the relational database schema (called Object/Relational Mappers); there are other ones intended to achieve a clean MVC componentization; and recently, a new generation of dependency-injection frameworks is dominating the scene. Dependency injection allows a component to not to be responsible for knowing what its dependencies are, it just has to know which interface they expose. Thus, any tier change will not impact on its associated classes, because they do not know each other directly. The undeniable success of dependency injection frameworks coined a reputation for them as lightweight (application) containers, in opposition to heavy, all-or-nothing solutions. There are some other specific-purpose frameworks: integration, monitoring, and so on. These all share one concept: to keep developers focused on business logic (functional requirements) instead of cross-cutting aspects like security, manageability, and other non-functional requirements.

Emerging Architect RolesEconomic changes, like globalization, technological achievements, and the Internet's impact on the digital economy, pressed for formalizing software architecture as a discipline. Although there is not yet a definite agreement in the distinct roles, we can sketch three major personas:
Infrastructure Architect. These define the platform and other environments (hardware, basic software) for business applications. They must also work with developers to define mechanisms and standards that allow applications to achieve the security, reliability, manageability, transparency, and policy compliance essential to the modern business. It's expected that the natural evolution of a senior IT professional is to become an Infrastructure Architect.
Solutions Architect. These are responsible for the design of one or more applications or services within an organization, usually within the scope of a division (and for that reason the role is also known as Application Architect). Examples of such applications are: Internet banking, company-wide knowledge sharing portals, and distributed point-ofservice (POS) applications. A senior developer is a good candidate to become Solutions Architect.
Enterprise Architect. Their job is to keep the business and its IT systems in alignment. They strive to maximize the return on IT investment by making sure that IT spending is prioritized towards business opportunity, and by optimizing the impact of investments across the organization's portfolios of services, resources, projects, and processes. They must act as a bridge between business leadership, development, and operations to ensure mutual understanding, realistic goals, and properly managed expectations. Enterprise Architecture is about the big picture -- how people and technology work together to produce world-class, long-term results. For that reason, this persona is also referred to as a Strategic Architect. What is expected is that a Solutions Architect or Infrastructure Architect becomes an Enterprise Architect.

What Software Architects are Concerned With TodayRecent years have been really challenging for software architecture. An elemental concept like service-oriented components (and its implementation using Web Services), gave place to a whole enterprise strategy known as Service-Oriented Architecture (SOA). SOA has as a goal the complete connection of the business application portfolio. Former silos like company CRM, ERP, and every other line of business (LOB) application, are expected to expose their functions to the others for synergy and mutual profit. The SOA challenge can be organized into five major areas to address:
Federated Identity and Access: How do we manage the authentication and authorization systems in a centralized way, available for every application? Once the user logs in, how do we propagate that identity to every service? How do we treat external customers compared to internal users? Do we treat them as just another role, or maybe we should consider a completely different policy?
Federated Data. How do we keep the distributed repositories synchronized? How do we gently gather enterprise entities by data aggregation? Which levels of redundancy are reasonable? How do we deal with offline situations?
Business Processes. Service-oriented components are granular pieces combinable in business workflows. Thus, every service could be seen as an activity to be executed in a definite order and upon definite conditions. The workflow engine becomes a sort of infrastructure piece in an SOA.
Service-oriented components. There are four tenets that the pieces must comply with to meet the SOA goals: explicit boundaries, autonomy, contract sharing, and policy-based compatibility. Those premises are discussed in more detail in an MSDN article Principles of Service Design: Service Patterns and Anti-Patterns.
Integrated User Experience. What does an SOA UI look like? There is a new range of UI frameworks around the concept of composed applications. We can find examples of them in CRM solutions and Web portal engines, where the UI is built through a combination of simpler, connected UI components.
The MSDN Architecture Center provides a complete reference of these capabilities.
Where Software Architecture Goes from HereWhile concepts like patterns and SOA are already or are becoming mainstream, software architecture continues evolving and expanding to new spaces. Although this article is too short to discuss all of the other software architecture trends which build on SOA, like model driven architecture (MDA) or software factories, you can find more information on the Software Factories page in the MSDN/Architecture Center. There are two particular topics, not yet massively embraced but watched very closely by the industry and worth mentioning, they are:
Software as a Service (SaaS). SaaS is a new software delivery model, where companies do not really hold their LOB software bits, but only its right of use. From this, a new concept of software provider emerges (the so-called SaaS provider). Clearly, from the enterprise perspective, the inclusion of such software implies a certain impact. How do we combine a SaaS application, for instance, in the company's SOA? How do we manage identities, workflows, and so on? From the provider perspective: a multi-tenant issue arises. If the provider is renting the software - its infrastructure - to more than one enterprise customer, how can they enable further customization? Consider as examples various database schema, country policies that impact business processes, and other customer specific modifications. Perhaps even more pertinent, how do we scale the environment for a growing number of tenants? The MSDN Architecture Center granted Software as a Service its own space. Visit this page to learn more.
Web 2.0. Another area of architecture research is how to get the most of the writable Web, that is the Web based on participation. We talk about Web ads, blogs, wikis, and other implementations. Those participative applications have existed for a while. The point is how companies can benefit from them, merging these kinds of community applications into their enterprise architecture. How do we offer "the long tail" of those goods and services, each of which individually may not be the most desirable to implement (possibly the least), but surely all of them together are becoming important in terms of revenue.
Conclusion
We have reviewed how software architecture evolved from what software engineering was realizing about its existence, and the shifting of roles due to componentization. The first software architects were de facto architects, in the sense that nobody officially granted them such titles. It was just a common perception, a sort of consensus. But now software architecture is leaving behind its alchemist stage to become a scientific discipline.