Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where Can I Find Examples of Procedural Code Converted to Object Code

Tags:

.net

oop

I'm trying to wrap my head around Object Oriented programming. But I'm having some trouble. I (think) I understand the general concepts and the arguments for why OOP is a 'good' design. My problem comes when I sit down and try to write code that is OOP.

I tend to end up with programs that are either very procedural but have the occasional object tossed in for good measure....or programs that seem ridiculously long and complex for what they are doing....everything is an object; but there are many, many objects and the inheritance trees get long and ugly.

What I've been trying to find is some non-trivial examples (I've seen plenty of throw-away/pseudo code involving cats, dogs, and animals....but they don't seem to help when I actually try to code up something that needs to do something) of really well designed OOP source code. Ideally, I'm looking for something that would step me through the thought process. Like 'Okay - here is some procedural code that does XYZ. Now, here is some really great OOP code that does the same thing!'.

Thanks

like image 262
Rob P. Avatar asked Aug 28 '09 16:08

Rob P.


People also ask

What are the examples of object-oriented programming?

Significant object-oriented languages include Java, C++, C#, Python and Javascript. The simplest way to explain object-orientated programming to a kid is to use something like a car as an example.

What is procedural object programming?

Procedural Programming can be defined as a programming model which is derived from structured programming, based upon the concept of calling procedure. Procedures, also known as routines, subroutines or functions, simply consist of a series of computational steps to be carried out.

What is your take about procedural programming and object-oriented programming?

Object-oriented Programming uses classes and objects, Procedural Programming takes on applications by solving problems from the top of the code down to the bottom. This happens when a program starts with a problem and then breaks that problem down into smaller sub-problems or sub-procedures.

How are objects programmed?

An object stores its state in fields (variables in some programming languages) and exposes its behavior through methods (functions in some programming languages). Methods operate on an object's internal state and serve as the primary mechanism for object-to-object communication.


4 Answers

The reality is that such conversions wouldn't generally be good object oriented code. Why? Because object oriented code isn't simply moving functions into methods and data into members.

Instead, a good object should be responsible for all of its data and only take method parameters where those parameters are defining the data that will be operated on.

This means there isn't a 1:1 mapping from procedural functions and procedural data structures to the object oriented ones.

Having taking a look around I didn't find any examples I cared for online, so I will simply give my refactoring rules for converting procedural code to OOP.

The first step is to simply package each module as an object. In other words, just create an object that holds the data and the functions. This is horrible to a purist, but you have to start somewhere. For example, if you had a BankAccount module, you will now have a BankAccount object.

Obviously the functions were having the data passed into them from external calls. Here you are looking for how to internalize that data and make it private as much as possible. The goal should be that you get your data in your constructor (at least the starting point) and remove the parameters that used to receive the data manually and replace them with references to that now private data. Using the BankAccount object, all access to the account is now via methods on the object and the actual account data has been internalized.

Many of your functions probably returned modified versions of the data structures: stop returning that data directly and have these modifications stay within the private structures. Create accessor properties that return your now private data where necessary and mark them "obsolete" (your goal is to make the object the master of its data and only return results not the internal data). With the BankAccount object, we no longer return the actual account data, but we have properties for CurrentBalance and methods such as AverageBalance(int days) to see the account.

Eventually you will have a set of self contained objects which still bear little resemblance to what you would have done if you started with objects in your design, but at least you can continue your refactoring with your new objects. My next step usually to discover that the objects created from such refactoring have way to many responsibilities. At this point some common threads probably have been detected and you should create objects to refactor these common ideas into. If we have BankAccount, we probably have other account types and if we align the methods of all of these account types we can make Account as a base class that implements all the shared features while BackAccount, SavingsAccount and others implement the details.

Once the class structure starts to take shape it is time to feel better about the conversion. Refactoring is a process, not an endpoint, so I generally find that my class structure continues to evolve. One of the nice things about having gotten this far is that your data is private and manipulated through methods, so you can refactor the internals more and more freely as you progress.

One thing that makes this plausible to do is having good unit tests. When doing procedural to OOP conversions, I often keep the old code around as the "baseline" so I can test against it. I.e., the test can verify against the old procedural system's results. If you don't match up, it is a good idea to find out why. I find that often there is a bug... but sometimes your new cleaner code is actually doing something right that was wrong in the past.

Regarding creating "too deep" of object trees: that can be the result of getting too obsessive about inheritance. I find that composites often are a better idea, where you implemented the interfaces for multiple objects rather than trying to get all those features into a single parent object. If you are finding yourself creating parent objects that simply are blends of feature sets, consider simplifying by making an interface for each feature set and implementing those interfaces.

like image 87
Godeke Avatar answered Oct 12 '22 23:10

Godeke


The problem procedural programmers often have when starting object-oriented programming is they keep designing procedures and try to organize them as objects. That doesn't work.

Object-oriented programming is a different design methodology; a different way of thinking about the roles and responsibilities you distribute throughout your code, not just a different coding methodology.

When you get past the "dog is-a mammal" metaphors (which never translate to real applications), I would recommend this book: Object Design: Roles, Responsibilities, and Collaborations. It was the first book I read where I finally got why I had to stop viewing (in my case) C++ as "C with classes thrown in".

like image 28
Robert Cartaino Avatar answered Oct 12 '22 22:10

Robert Cartaino


One very intuitive transition from a C API to a C++ API happens a lot in databases; so for this example, we'll take a quick look at the difference in using the MySQL APIs.

I'm not sure if I can copy the code from these sites (no idea what license it is), but look at the section labeled "Creating a Database" for a C demonstration, and Sample #1 for a C++ demonstration; both of these step through creating a MySQL database programmatically.

In the C API, the first argument to every function is a "handle" to the database. In the C++ API, we work with a database connection object which implicitly calls the C API with its private handle.

To look at one very specific example, to execute the query once it's been generated we have in C:

mysql_query(conn, "create database testdb")

and in C++:

query.execute();

The big difference here is that the C++ binding only shows you as much as you need to see, while in C you have to be very explicit about every little detail.

I think the database APIs are a good way to pick up some OOP principles by example, so hopefully they can help you out too.

like image 30
Mark Rushakoff Avatar answered Oct 13 '22 00:10

Mark Rushakoff


I know this is tagged .net, but a good example would come from PHP. Before PHP5, PHP was only partially object-oriented. Many PHP developers had the very same problem of grasping OOP.

Zend has a pretty good article here. It should be pretty easy to follow.

If you feel like you need better direction with the object oriented design process, you may want to check out MIT's Open CourseWare, specifically Foundations of Software Engineering (Lecture Notes #2) or something similar.

like image 34
Jim Schubert Avatar answered Oct 12 '22 23:10

Jim Schubert