Motivations To Develop Object-Oriented Solutions With a basic theoretical understanding of what collections represent in an object-oriented world, let's discuss what object-oriented development brings to the table. It is often said that software is written to solve a business problem. This statement isn't true, in my opinion, in the majority of the cases. More often, software is written to enhance a business process. There is rarely a case where software is the only way a business can "solve a problem." More common is developing software to improve or expedite a business process by increasing operational efficiencies or removing tedious repetitive tasks.
Two common approaches to software development are functional decomposition and object-oriented analysis and design, also known as business modeling. Functional decomposition focuses on identifying very specific areas and determining the exact functions needed to realize application functionality. Each requirement is decomposed into its constituent functions. This type of analysis approach often leads to a very procedural system relying on specific function calls from start to finish to achieve the desired resultsThe cost of building software in this manner is that the natural relationships between entities within the system are not modeled. A system developed using functional decomposition is often very efficient within the specific area it was designed to automate and quick to build, however, it is typically very brittle when it comes to adapting to changing business requirements or enhancing the functionality. Often, these systems do not create many reusable components outside of the utility space.
The second approach, object-oriented analysis and design, develops software that models the business process through objects representing real-world elements. This process typically involves understanding the business need and creating models, often through Unified Modeling Language (UML), to capture the interactions and processes that deliver the needed functionality. The models are then used to identify and define the classes that will ultimately become the application elements. The business requirements are then met, not with a precise execution of function calls, but rather through the interactions of the objects within the system, much the same way in which the process the software is mimicking achieves results. Because a process is emulated, it is easy to change how the key players within that process, the objects, interact when the real-world process changes. This allows greater flexibility in adapting applications to changing business requirements. Also, businesses are not disconnected entities. The same notion of a customer may exist within numerous elements of a business, from marketing to customer service to accounting. By creating software constructs that model these entities, we can also get a larger amount of code reuse through well-designed objects.
Another benefit of using an object-oriented approach to software development is the inherited Application Programming Interface (API) that is developed as a result of the object associations. Suddenly, operations such as saving the data associated with a person become very intuitive, especially with the IntelliSense built into the Visual Studio .NET (VS .NET) Integrated Development Environment (IDE). Figure 4 shows the difference between a sample procedural system that uses an administrative module to perform functions, such as saving user data, and an object version of the same system. While both approaches technically use objects (after all, everything in .NET derives from the type System.Object), I like to term the two approaches object-based development and object-oriented development. Object-based development is more procedural in nature and does not necessarily combine data and behavior within the same class, while object-oriented development does keep behavior and data in the same class.
Figure 4a - Object-based code sample Figure 4b - Object-oriented code sample One example of where the intuitive API that emerges from an object-oriented system lends even more benefit is in larger projects where you have separate teams working on the user interface (UI) and the business logic. I was involved in a project some time back where there was a team of ASP user-interface developers that were not familiar with middle-tier or database development. There was a separate team of object developers that implemented the business logic in COM / COM+ objects. It was very easy for the user interface team to use our objects without having to know how our objects were implemented. Those developers did not have to have volumes of documentation to look up information such as what function within what module needed to be called to update user information, as the code structure in Figure 4a would require. Instead, they simply knew they needed to grab an instance of the user object that they needed, set the properties, and call the update method, as in Figure 4b.
Benefits of Custom Collections in .NET Hopefully you are starting to see some of the benefits of moving to an object-oriented approach to software development. Let's look at some specific reasons to implement custom collections. You may say, "I understand why it is important to have a customer object, but I can just use the Rows collection of a DataSet to represent a group of related customers. After all, isn't the DataSet an object and the Rows object a collection?" Technically this is an accurate statement that raises valid points. A DataSet is an object and the Rows attribute of the DataSet is a collection. Additionally, the .NET Framework provides powerful methods of binding DataSets (as well as DataReaders) to display elements such as grids and drop-down lists with very little custom code. Another point is that a DataSet is easy to retrieve; it is the native form of retrieving data from persistent data stores such as Microsoft SQL and Oracle.
However, when compared to a custom collection, a DataSet is a very generic object; it can represent everything from a collection of customers to a collection line items associated with a purchase order. While this serves a purpose in retrieving data from the database and perhaps providing an implementation-agnostic transport mechanism, it is not the best choice for a system that wants to model specific, real-world entities as objects.
Additionally, a true object collection contains individual elements, i.e., the objects that can model real-world behavior through custom operations. The constituent elements of a DataSet, the DataRow objects, cannot provide this same level of custom behavior. Another limitation of DataSets is the code that consumes them needs to have intimate knowledge of the data schema. Perhaps the object that needs to be represented is stored in multiple tables in the database. Or perhaps your database-naming scheme does not match the naming scheme of the properties of an object. Although the latter point could be fixed by renaming the columns as they are selected from the database, this is an extra-tedious task that needs to be completed. I have provided two code samples in Figure 5. One shows iterating through a collection of objects and the other shows iterating through the DataRow collection of a data set to pull out the same data. You'll probably agree that iterating through the collection is more self-documenting and intuitive than using the DataSet Rows collection.
Figure 5a - Iterating through a collection of objects Figure 5b - Iterating through the DataRow collection of a DataSet