In this video, we'll talk a bit about what object-oriented
programming is all about.
But before we do that, let's review procedural programming
and its limitations.
Procedural programming is pretty much what we've been doing up
to this point in the course.
The focus of procedural programming is the function.
We modularize our programs by creating many functions that each specify a
process or action in the program.
So procedural programs are basically a collection of functions.
In procedural programming, we declare our data separate from the functions.
And then wherever we need to function to process or use our data, we
pass in the data to the function.
If you recall our challenge from section 11, that's
exactly what we did.
There's absolutely nothing wrong with procedural programming.
And in many cases, you have to use it since not all languages
support object-oriented features.
Procedural programming is also fairly easy to learn since we're
pretty good at breaking up a task into subtasks, which is exactly what
procedural programming is all about.
However, procedural programming has some limitations.
One of the limitations with procedural programming is that
the functions need to know about the structure of the data.
This may not sound like a big deal.
But suppose we have a program with hundreds of functions and many of
those functions expect a specific data structure as an argument.
If the structure or format for that data structure being passed
around changes, then this would affect many many functions.
These functions might even have to be modified to handle
the new format of the data.
This could have a ripple effect in the program and the amount
of effort needed to change and then test all of the updated
functions could be substantial.
I've worked on very, very large projects where the decision was
made not to upgrade a data structure because the changes needed in the rest
of the program would be too expensive in programmer and testing time.
The real limitations to procedural programming really
begin to show as programs become larger and more complex.
As procedural programs get larger and larger, they become more
difficult to understand since the number of connections in the program
becomes very hard to trace by hand.
This leads to problem maintaining the software, extending the program
and finding and fixing bugs.
Also, reusing functions and data structures that we wrote for one
program in another program becomes much more difficult since after time
we end up with code whose behavior isn't that easy to visualize.
Finally, the code becomes more fragile and easier to break.
That means that when we add new functionality or
fix a bug, the chances of introducing another bug is high.
This happens more often than you would think.
And it happens more in large procedural programs than it happens
in large object-oriented programs.
Okay, so now let's talk about some of the principal features
of object-oriented programming.
So what is object-oriented programming all about?
In this video, I'm focusing on object-oriented
programming and its benefits.
We can also have object-oriented analysis, object-oriented design,
object-oriented testing and so forth.
Object-oriented is all about modeling your software in
terms of classes and objects.
There's some new jargon to learn along the way, but it's not so bad.
Don't worry if it all doesn't click right away.
We'll be using this new terminology a lot in the rest of the course.
These classes and objects model real-world entities
in your problem domain.
So if you're writing an application that allows users to store, edit
and manipulate images, like iphoto on a mac or photos on a PC, then
your classes might be album, photo, slideshow, location and so forth.
If you're modeling a student enrollment system, your classes
might be student, course, professor.
You get the idea.
Why is this such a big deal, and how is it different
from procedural programming?
Well, first, let's talk about why it's such a big deal.
It's all about abstraction.
As our programs grow more and more complex, we need ways
to deal with the complexity.
Classes and objects are one way to do just that.
Now rather than thinking in terms of first name, last name, student
ID, credit hours and so forth, we can think in terms of student,
and all that detail comes along with it.
Not only that, but operations like register, drop course, add course and
so forth, also come along with it.
So if Frank is an object and it was created from the student class, I
can send a message to Frank and ask Frank if he's registered this term.
This is very different from procedural programming where
I would have a function that would tell me if the student is
registered and then I would have to pass a student to that function.
You might ask so what it still works in procedural
programming, and you'd be correct.
But now the function needs to know how to determine if the
student is currently registered.
If this business logic changes, then we need to figure out
everywhere in the program that knows this so we can update the code.
In the object-oriented solution, only the student class knows
this, so a precise change is all that's necessary.
The fact that objects contain data and operations that work on
that data is called encapsulation.
And it's an extension of the abstract data type in computer science.
Now the data and the operations are together in the class where
they belong and not spread across many functions each
passing and receiving data.
Encapsulation is another mechanism used by object-oriented programming
to help us deal with complexity.
We can take the idea of encapsulation even further with information hiding.
Object-oriented programming allows us to hide implementation-specific
logic in a class so that it's available only within the class.
This is a super powerful concept since it allows us to provide
a public interface to the class and hide everything else.
Now we know that the user of the class can't mess with the
implementation-specific code since they never knew about it in the
first place, that's pretty cool.
This makes the code easier to maintain, debug and extend.
Object-oriented programming is also all about reusability.
Reusability is defined in terms of using something from this
program in another program.
Since classes are pretty much encapsulated units of data and
operations reusing them in other applications is much easier.
And since the class has already been tested, we get that benefit as well.
This leads to faster development and better quality software.
Finally, you've probably heard about inheritance.
Inheritance allows us to create a new class based on an existing
class by only adding or modifying the elements that we need to be
able to create our new class.
For example, suppose we have an account class that
models a basic bank account.
So it has a balance and the regular withdraw and deposit methods.
Now suppose we have the need for a special trust account class.
And our business logic says that this type of account is limited
to three withdrawals per year and each withdrawal can't exceed 10%
of the current account balance.
We could add this logic to the account class that we already have and have
an enumeration or some other kind of discriminant that determines what
type of account we have and then execute the appropriate if else logic.
Sure, that works.
But what if we expect lots of variations to that account class,
like a money market account, a CD account and so forth.
And each one of them has its own business logic, not only for
withdrawal, but also for deposit.
And some accounts change fees and others produced interest income.
You get the idea.
This could quickly make that simple account class that we
started out with, a beast that no programmer wants to deal with.
In this case, we can derive our new class from the existing account
class and add the appropriate behavior in the new class without
modifying the original class at all.
This leads to reusability as well as polymorphic classes, since all
the derived classes we created are in fact still accounts.
We'll learn more about the power of polymorphism later in this section.
So oo sounds pretty amazing, right.
Well while oo can certainly help us develop large programs that are easier
to maintain, test, debug and reuse components from, it's not a panacea.
Oo won't make bad code better, it will likely make it worse.
Also, oo is not suitable for every application, and not
everything decomposes into a class.
There are sometimes non-functional requirements that horizontally
cross-cut a system, and these tend to add tangled code
within existing classes.
Remember, if you have a small program that won't be around for
any significant amount of time, maybe it's an internal program
that you're using to automate something, then object-oriented
programming might be overkill.
A simple procedural or scripting program may be perfectly appropriate.
Generally, object-oriented programming has a steeper learning
curve than procedural programming.
C++, in particular, is considered one of the most difficult
programming languages to learn.
Also, there are many object-oriented languages out there.
And while they all support classes and objects and so forth,
the way that they support them can be quite different not only
syntactically but also in behavior.
As mentioned in the beginning of this video, it usually takes more
upfront design time in order to write an object-oriented program.
In fact, large object-oriented programs sometimes go through
significant upfront design.
Finally, object-oriented programs tend to be larger in size than
non-object-oriented programs and can sometimes be slower and more
complex since there's so much more going on behind the scenes.
This can be especially true with object-oriented languages
that use a virtual machine.
However, the great news is that among object-oriented languages,
c++ is probably the most efficient language out there.