Can OO Programming Solve Engineering Problems?
"I appreciate the concepts of OOP and see its applicability in managing records, GUIs, and possibly standard function libraries. I cannot, however, convince myself that there is a clean way to use these concepts to solve the type of procedural problems that I have encountered in the past (finite difference solutions to differential equations, finite-volume computational fluid dynamics, iterative solutions to non-linear equations, Monte-Carlo simulation of radiative heat transfer, etc.)
Am I just being close minded to the ideas of OOP or do my problems just require 'procedural' solutions, which are better solved using procedural techniques? I'll even be happy with the answer 'Your problems are two small and specialized to realize any significant advantages of OOP.'
I'd be interested in hearing comments from anyone else who has this problem, anyone who has worked through it, or anyone who can send me an example of an engineering application of C++ and OOP."
Your problems are too small and specialized to realize any significant advantages of OOP.
Most engineers have been taught that FORTRAN is the way to solve problems in engineering. If everyone starts out with that prejudice and is stuck there.
Where I work, there is a project to write an engineering application in VB, and it has seemed to be one problem after another after another. (I know i know, VB is crap). The core library functions are in C, in a DLL, so I guess thats a bit of a start.
FORTRAN has been ingrained into the current working generations of engineers, so they're going to use what they know.
Heck, I've even seen SQLPlus code (from Aspen) written very very very FORTRAN like. Instead of using min(), max(), there was a bunch of select looping and checking variables..... Oy.
This is a really difficult question to answer. I guess my reply would be that no, pure "OO" programming wouldn't hold any advantage to simple procedural programming in this case. However, you can easily add procedures to objects, so OO language is really just a superset of procedural.
Personally, I like the organizational potential of OO. You can have a Pipe object, and call function like Pipe.calculateFlowrate(12,43,23), then you could have a subclass SquarePipe, and call the function SquarePipe.calculateFlowrate(12,12,43,23).
Essentially, you could have 10 objects each with 10 functions to do 100 different tasks, rather than 100 different functions to do 100 different tasks.
Moderation: Put your hand inside the puppet head!
There are a number of ways to approach this, but I've found the following useful:
It's more a matter of thinking in terms of telling your processes to do stuff than creating a road for them to walk down. If you know what I mean
All your Qaeda are belong to US
OO design has nothing to do with C++ versus C. You can do OO design with any language you like; much of the Linux kernel has elements of OO design, but is implemented in C.
Language is an implementation detail. It does not dictate design.
Twoflower
--
Twoflower
I'm not terribly familier with the problems you have presented (I.E. I know what a monte carlo alogorithm is, but not the radiative heat transfer part...), but it sounds to me like you're trying to fit the problem to the solution and not the other way around. OOP can be useful if you're trying to model something, or replicate the behavior behavior and characteristics of a real world problem, but it's not that great for say, solving a system of equations... I guess you can use whatever language or system you would like, but not many need C++ and the STL to evaluate expressions.
All of the techniques you listed and most other engineering problems are expressed in a procedural format. In order to use OO you would have to transform the problem into an object problem. The things that OO does really well at are things where we already think in object terms. Like GUI widgets. Most engineering problems simply aren't expressed that way. Although most problems could be rephrased that way the algorithms would necessarily not be equivalent (better or worse would require experimentation)
If you're dealing with a problem that can be reduced to a mathematical formula or the like, you're probably better off looking in Numerical Recipes or the NAG libraries, or what have you.
In this case, you're dealing with a well-defined, well-understood problem. You could implement a solution using OO principals, but why bother. I mean, you're not going to be changing it or adapting it all that much.
The power of OO happens at a higher level, and with less-well understoof problems. In this case, you're modeling higher-level entities, with less well-understood properties that are much more liable to change. In this case, the ideas of modularity, pluggable behavious, cohesiveness, etc., become much more important.
I hope that didn't sound too much like a hand-waving explanation.
668: Neighbour of the Beast
C is a procedural language, not a functional language. Examples of the latter include LISP, Scheme, and ML.
As to whether an object-oriented approach is suitable for engineering applications, I think it depends on the applications and problems. How important is abstraction and re-use? If you deal with matrices, would you benefit from a matrix object which implements all the properties a matrix has? With differential equations, are there objects suitable for implementation?
As with all general questions I am afraid the answer is "It depends."
OOP doesn't solve engineering problems of the kind you describe. The programs solve the problems.
OOP is a way to think about structuring the program, how you organize data and operations on the data, how you build reusable components which you can apply in some future problem you need to write a program to solve. In other words, OO helps solve software engineering problems. You'll still need to write the program which solves your particular problem.
And before the flames commence, yes, OO isn't the only solution to this class of problems. It's just one.
How do you write a million lines of maintainable code in six months with 5 programmers in Silicon Valley and 50 in Turkey? Hint: You don't do it in C.
Take a look at BLITZ++, then tell me OOP is not useful for scientists and engineers. :-)
I think the safest thing to say is that whatever your programming needs, whether you're doing pure matrix/BLAS number crunching or writing complex simulations/models, you should think twice before using FORTRAN. Well-written code in, say, C++ will be more maintainable and accessible to other people you work with (and who have to touch your code in future).
The only thing which keeps people using FORTAN that I've seen is that the optimising compiler support is fantastic compared with the equivalent offerings in C/C++ compilers. But that's not much of an excuse for general day to day problem-solving.
Just my 2p.
These sigs are more interesting tha
That has been true in the past, but with modern compilers (like gcc) you will get very similar code and only a slight increase in overhead (vtables) with C++ over C. Lots of people are using C++ in small embedded systems now.
Real bloat comes from libraries like STL...
When you get down to it, every application, at some level, is a database of some kind. ie. it will end up storing many records of the same or similar type, usually in memory, and then go and do actions on those records. Weather each 'record' is a data packet, plugins for your application, records from some kind of file, whatever. In the end, it all acts a little like an in-memory database.
....) you would just do mystruct.do_something(...). Which when you think about it, is a more logical solution. Almost every function you write, except for the straight out code-flow, and accessor functions, is some kind of operation on a data record in your 'in-memory database' (however it is represented). OOP's main purpose is to more link the functions doing stuff to the data, and the data itself. Nothing more, nothing less.
.c file, and you know they're all related to that structure because they're in that particular .c file, you instead put all the functions in a class, and you know the funcitons work on that data, because the data, and function, are all part of the same logical unit.
... its just a cleaner way to group together data and functions that work on that data in a more 'binding' fashion, something that had to be done by the coder's memory and by hoping the previous coder's comments were good enough to make it clear what goes with what.
The traditional way to handle this kind of thing is with a linked-list or array of structures. The main thing OOP gives you is not any 'special' solution to old procedural programs -- infact, a good blend of procedural and OOP is always the best solution, because every program is a combination of both. However, what OOP does give you is a nice way to encapsulate all data that is relevent, instead of into a structure, into a complete package.
Instead of calling functions, and passing that object around, and then worrying about lost pointers, NULL's, etc. You take the more logical course of action, and perform the action directly ON the object. ie. instead of doing: do_something(mystruct,
Things like inheritance, templates, polymorphism, etc, are all just fluff to make coding easier, that has been added on top of the OO ideal. Granted, they make life ALOT easier (dont get me wrong, I use all of them all the time, and I'm an OO junkie), but the main purpose of OO is simply to create logical units, including code, and data in one block. So instead of having a bunch of structures, and then all functions to act on that structure in one
So I think you've mistaken the benefit of OO. As I said before, OO is not some kind of magical wand that will solve even the most complex of computing programming problems easily
Not really, but there is an element of truth to that mantra: most engineers traditionally learned to program in Fortran, and there were some damn good Fortran compilers/libraries to handle the types of matrix manipulations commonly encountered.
You don't need the overhead of OO design for your engineering programs. I would stick to C unless you are trying to do some kind of fancy GUI.
While abstract classes will incur the hit of an extra level of indirection in a function call, and exception handling in C++ can be expensive (as can multiple inheritance), these features only cost you if you use them.
Now, to answer the question at hand, I have helped to design and develop commercial speech recognition products using C++. Of course, there was plenty of C and hand-tuned assembler there as well.
A more concrete example would be the VFS in Linux, as well as the classes of network, block, and character device drivers -- while generally coded in C, they represent the notion of abstract base classes unifying a common interface to many different implementations -- there's no reason C++ could not have been used there.
You could've hired me.
First off you're examples Monte Carlo simulations and differential equations aren't "engineering problems". They are math problems that are a component of an engineering problem. Engineers does things. It builds a bridge, drives a car, prints a document. The examples you give are parts of that solution. Every GUI needs to do things like interpolate colors and position, which are the same class of problems -- if orders of magnitude simpler -- as differential equations and Monte Carlo simulations. So it seems to me that you need to figure out what your real problem is and figure out what programming paradigms might help you out with that.
As others have pointed out OOP doesn't let you solve things that are otherwise unsolvable. It is a way of solving problems that may be better in some situations and worse in others. The examples you give of solving equations are all better suited to a functional language than a procedural one like Fortran, so rather than asking "why use OOP" you might want to first ask yourself "why am I using Fortran?" Obviously there are a number of factors that go into how we pick our solutions. Maybe OOP per se isn't a good fit for your problem but you need it to be multiplatform and have a huge amount of available code and standard libraries so you end up going with Java. Or whatever.
The kinds of problems you're talking about don't have a great mapping onto the traditional ways of describing OOP. However, OOP is really just a somewhat formalized kind of way of dealing with abstraction and data encapsulation. You can make a difference equation a class. Maybe it'll only have one method that immediately finds all the finite solutions. But once it is a particular datatype you can also do things like compare whether two user-entered difference equations are identical and just returned the cached solution. You can curry them. You can return partial solutions and then come back later and ask the object for more solutions.
Don't you already have discrete data types for these things? And don't you already have functions that operate on those discrete datatypes? Then you're already doing OOP. Sure you're not using inheritance and multimethods and things like that. But not every OO program does.
OO languages exist at the "high" end of the language-level spectrum. They're geared toward managing code complexity in the face of a problem domain which is conceptually complicated, primarily by encapsulating bits of the problem domain into digestible and self-contained sub-problems. The overhead of all of the OO constructs is worth it if the reduction of your problem domain into smaller chunks is neccessary to solve the problem (or advantageous in terms of directing the efforts of multiple team members in areas where some decoupling is possible).
However, if you problem is "low-level" or conceptually simple (though not neccessarily computationally simple) -- a recipe like "apply transformation x to dataset y, then transform again w/ algorithm z", the OO features simply serve as a distraction from thinking about your actual problem domain and it's solution.
So yes, IMHO, there are problems for which OO techniques are not ideally suited, and most importantly, if the techniques get in *your* way they are not the right tool for *you*. Rememer, languages and tools don't solve problems. People do. If a tool makes you task easier, use it. Otherwise, save yourself the time.
For simplicity's sake, let's think about quadratic equations for a second. You can solve them easily, but if you want to use them in a larger program, you could create a QuadEq object in OOP with the following properties:
An OO programmer would then add methods to set, retrieve, and calculate those properties based on what's been entered. And the QuadEq object would be entirely portable and easily amplified for future equations.
I don't think choosing OOP is a matter of being the only tool to solve certain problems. However, it is often the most efficient way to solve large, rapidly-changing problems. But like you said, other problems (like many of the ones I encounter in web development) will be small and uncomplicated enough that the overhead of OOP isn't worth the trouble.
You seem to think that OO is some end all be all of the programing language. It is more on how you structure the code. You can do a hello world program using OO is you wanted. Instead of acting on the logic of the problem you design from the idea that the data is what must be manipulated and therefore is an object to be handeled. All the problems you are listed are easily solved by defining the class that is associated with the data inputs and then perform actions on those objects. It is quite a bit different in thinking over how fortran is programmed.Having programmed in both OO is a much more powerful solution.
Here is an excerpt from www.whatis.com that may explain this better than I can.
" The first step in OOP is to identify all the objects you want to manipulate and how they relate to each other, an exercise often known as data modeling. Once you've identified an object, you generalize it as a class of objects (think of Plato's concept of the "ideal" chair that stands for all chairs) and define the kind of data it contains and any logic sequences that can manipulate it. Each distinct logic sequence is known as a method. A real instance of a class is called (no surprise here) an "object" or, in some environments, an "instance of a class." The object or class instance is what you run in the computer. Its methods provide computer instructions and the class object characteristics provide relevant data. You communicate with objects - and they communicate with each other - with well-defined interfaces called messages.
The concepts and rules used in object-oriented programming provide these important benefits:
The concept of a data class makes it possible to define subclasses of data objects that share some or all of the main class characteristics. Called inheritance, this property of OOP forces a more thorough data analysis, reduces development time, and ensures more accurate coding.
Since a class defines only the data it needs to be concerned with, when an instance of that class (an object) is run, the code will not be able to accidentally access other program data. This characteristic of data hiding provides greater system security and avoids unintended data corruption.
The definition of a class is reuseable not only by the program for which it is initially created but also by other object-oriented programs (and, for this reason, can be more easily distributed for use in networks).
The concept of data classes allows a programmer to create any new data type that is not already defined in the language itself.
One of the first object-oriented computer languages was called Smalltalk. C++ and Java are the most popular object-oriented languages today. The Java programming language is designed especially for use in distributed applications on corporate networks and the Internet."
Papa Legba come and open the gate
I've seen some truly awful procedural code (lots of it was Fortran, BTW). I've seen some truly gorgeous procedural code (lots of it was Fortran, BTW). I've seen some some wonderful, and even more pretty awful, OO code (mostly C++, but with some Java).
Go ahead and study object oriented programming. You'll learn some new ways to do things. But I think it's the act of studying, and the act of learning, that will be the most valuable thing you get out of the process. Too many people never study how to program, how to document, how to design code. They learn one or more languages. Their code shows it.
A few people have a natural tendency to write elegant code. A few more, but still not very many, study and try to learn how to write elegant code.
But don't expect the object-orientedness to make much difference. A dozen or more years ago, a young whippersnapper got hooked on objected-oriented design. He derided all the existing Fortran we had as spaghetti code. To some of us, though, his "object-oriented" code was lasagna code. No overriding structure, code spread out all over the place, a single function scattered over three files. And this was still Fortran; I've seen C++ coders who took six files for a similar, simple function.
I've also surprised myself! when some of my OO C++ code needed four lines to add new functionality. But it was carefully designed, after years of programmer improvement and study.
Go ahead and try it; it can only help.
I think the "answer" to your question is that, yes, your examples are too simple. When you're doing some simulation where the "finite difference solutions to non-linear equations" all interact with each other, and with computed fluid dynamics and heat transfer, etc, you'll immediately see the benefit of separating all these concerns into encapsulating object types.
[
Imagine for a minute that you don't know what problem you want to solve yet. You know that that you want to apply a Galerkin Finite Element Method (for instance, though this particular method isn't required) to a whole class of problems on unstructured grids on a whole class of distributed and shared memory parallel computers. Imagine that you want your user base to be able to specify their equations like they would in LaTeX or some other markup language. Now try imagining that you have only FORTRAN77. Not a pretty picture. We're in the process of completing a rewrite of major sections of our parallel code to do exactly this. Our code started out (7 years ago) as an extremely efficient parallel (3D) C/F77 code for Navier-Stokes + Heat Transfer and is quickly growing into a multi-purpose, multi-physics code written largely in C++.* We extract considerable advantage form C++'s ability to hide implemenations so that as long as interfaces don't change the guts can. We also make good use of the ability to run code before main() in order to register the exisitence of routines (hash tables are your friend). If the routine isn't there you can't call it, but the code still compiles and runs otherwise. We also make use of base class/derived class relationships and polymorphism to allow, for instance, one base mesh class for the rest of the code to interact with, but with two separate derived classes: one to generate meshes internally, and one to read meshes from other programs. Etc., etc. I'm not sure our website can take the /.'ing, but you can look here for some hints.
* I say largely b/c there's a few struct's still left over from the code's C days, but all the F77 is gone. There are still calls to assembly coded (vendor supplied) BLAS routines, though.
Yes...I am a rocket scientist.
From your post is sounds like you're solving single solution problems where you write a 'disposable' procedure (probably reusing some code) for each problem. OOP isn't designed for that.
OOP really starts to shine when you actually have objects to work with. If all you're doing is trying to solve a single solution problem a simple 'disposable' procedure is the best route. For larger, evolving, iterative projects OOP is a godsend. In my case, I'm designing a MAV (Micro Air Vehicle).
I'm using Python instead of C++ but the OOP example still holds. Aircraft design is a highly non-linear process, and for myself at least, counter-intuitive. I could write a single procedure to run the analysis but that's not nearly a flexible as an OOP solution.
Basically, I'm using off-the-self components (i.e. motor, batteries, propeller) as a starting point for my design. Each of these components is considered an object. These components are combined in such a way as to make another object: the entire MAV. By using OOP it's rather easy to try different component configurations and design conditions (flight altitude, cruise, loiter, velocity, etc).
If I was really cool (I'm not) I could add in some simulation stuff (Larger aerospace corporations do a lot of this, as it's cheaper and quicker than an experimental approach).
One thing that this sort of OOP approach lends itself towards (especially in my case, is genetic algorithms). Since aircraft deisgn is so non-linear, and counter-intuitive the best solution is not easy to find. So many different designs need to be analysed. OOP and genetic algorithms were born for just this sort of thing.
If you have a single problem that needs to be solved once for one set of conditions, then use a procedure. If you have a larger project that requires the solution of many smaller problems for various conditions (instances to use the OOP term) then OOP is an easier route. Anything in between is a judgment call and really depends a lot on your specific case.
Preface: I've been an embedded systems software engineer since 1987. I've been programming in C for almost all of that time, and C++ since '91. I've designed systems with over 250kloc, hard realtime.
The biggest single advantage of OOD is that you can say "This sort of thing will have a function that does something like this, but I won't make the final decision on exactly HOW to implement that function until late, when I have more information on what needs to happen."
Let me give you a concrete example. I had to design the code to reprogram the flash in one of our devices. I faced the following problems:
1) the way the data got to us could either be Xmodem or Ymodem.
2) The file format could be either OMF or raw binary.
3) The types of memory devices could change - they could be Intel type 1 flash, AMD type 1 flash, or Intel type 2 flash (or RAM), all of which have different programming requirements.
3a) In addition, the types of flash could be changed by the production line (based on what was available - most of those parts were "on allocation", meaning "you take the quantities we give you and you like it - you ain't IBM so you don't matter".
3b) The types of flash on a given unit could be mixed - you had to probe at runtime to figure out what you had.
So, here's how I decomposed it:
1) I had two file type objects: OMF and Binary. They each HAD-A Input object, which provided data , and HAD-A Memory object, which would program memory. The OMF object read OMF records from the Input object, parsed the OMF records, extracted the data, and commanded the Memory object to program regions of memory.
2) I had an Xmodem object, which WAS-A Input object. It read data from the serial port, handled the checksum or CRC verification, block counting, and made the data available to the user (the file object).
3) The Memory object HAD-A pointer to a Memory_driver object. When the Memory object was commanded to write to a block of memory, it verified that the write was in the current block, and if so passed the request to the Memory_driver object. If not, the Memory object HAD-A list of Memory_driver_list objects, which each HAD-A pointer to a function that would probe a given memory address and return either NULL or a pointer to a newly created Memory_driver object. The Memory object would iterate through the list, asking each Memory_driver_list object "Can you program this?". When one of them returned a non-null value, the Memory object would delete the old Memory_driver, and use the new Memory_driver.
4) I had Intel_series1, Intel_series2, AMD_series1 and RAM objects, all of which WERE-A Memory_driver. Each class HAD-A static instance of a Memory_driver_list object, which automatically linked itself to the driver list. Each driver HAD-A static member function to probe memory and return a pointer to a newly created driver if needed.
First, this let each routine be focused on what it needed to do - the Xmodem routines didn't worry about OMF format, the OMF didn't do Xmodem handshakeing, the Memory routine didn't care about the specifics of programming memory. I could test each object out in isolation, get it working, and move on. Now, you can do this with proceedural programming techniques too.
Second, when a new type of memory was added, I was able to just write the driver for it, and not touch the OMF object, the Memory object or the file transfer objects. They automatically picked up the new driver. Now, you can do this in a proceedural language like C, but how do you do so? You make each driver have a table of function pointers, and you have the upper level code keep track of a void * that contains your driver information. Guess what - that's OOP! The function table is the same as a C++ vtable, the void * is your this pointer. Except that in C, you have to track all that stuff yourself, in C++ you can let the compiler worry about the BS and you focus on the code design.
In short, OOD helps, but you still have to use it correctly.
www.eFax.com are spammers
However, I have lots of bad experience trying to get engineers to write good OO code. Nothing against y'all, but, conversely if you forced most software engineers (aside from a few savant freaks that I'm sure will chide me) to deal with the engineering problems you mentioned (that I have never heard of or forgot) we would probably die.
What I'm getting at, I guess, is that OO rules. However, it's like linux, or repairing cars, or (ad infinitum). Being an expert rules, but it's not always worth the time to become an expert. You can't just jump in. Reading a few books helps, but I've read a few books, been doing this full-time for two or three years, had a very OO college experience, and most of the stuff I design and code is still crap.
In addition, the code you are writing seems really unlikely to change. Write it procedurally, and write it well, and your grandkids will still be using that code because it would be too much of a pain to rewrite it to OO.
I think you might be looking for an exemption. Here it is : use procedural programming for things that are tough for you to imagine in OO terms. Don't feel guilty. You will still never have as much crap code lying (laying?) around with your name on it as I do, and I do this for a living ;)
Jack Valenti and the MPAA are to technology as the Boston strangler is to the woman home alone
I have always thought of OOP as fundamentally a procedural programming technique but extended to give you better ability to organise and manage larger projects. C++ is a superset of C - you don't have to use the OOP features but they can help you enormously in the right situation.
:-). In this case, all the code that used the object would remain the same, possibly saving you a load of work.
OOP also encourages good programming practices like producing well-defined interfaces, implementation hiding and code re-use. I actually think these are crucial to the effectiveness of OOP. These are all good things, and I'm sufficienctly lazy that I would never write anything other than a trivial program in purely procedural style.
However, OOP is still best suited to particular domains. Modelling, GUIs, enterprise applications, games etc. are perfect because they all require the manipulation of discrete and readily identifiable "objects" that map onto the OOP model very well.
If you're writing network drivers, you could use OOP, but as other posters have been keen to point out the (very small) overhead of most OOP languages actually becomes a problem for very low-level code. Hence OOP isn't so well suited for OS kernel code, network protocols, hand optimised inner loops and embedded applications.
The difference between procedural and OOP is mainly a trade-off between low level control of the machine and having a semi-automated system to manage the complexity for you. Interestingly, for larger projects, good programmers in procedural langauages often end up having lots of function calls that take the "object to be acted on" as an argument and are therefore effecively emulating method calls. Once they start putting in switch statements in those functions to branch on the type of object encountered, they have effectively emulated virtual methods.
Your case is an interesting one. You are dealing with mathematical/engineering problems that are often tackled in a procedural style.
If you're feeling adventurous, I would actually suggest you head off to look at functional langauges. Reason is that these langauges are ideally suited for representing functions and other mathematical constructs, just as OOP is geared towards representing and manipulating "objects". Haskell would be my no.1 choice if you're looking for elegance and flexibility, O'Caml if you are more concerened about raw performance.
If these seem too radical a departure, then I still think that OOP could make sense for a major project. You probably wouldn't need inheritance, but implementation hiding can be very useful. Let's say you're modelling fluid dynamics, and do it procedural style with a big array. Works fine until you decide that in fact you want to store the data in an octree so that you can get a couple of orders of magnitude better resultion in the particular areas you are interested in. At that point you have to change everything that accesses the data structure, including the 100 or so simulation programs you've been developing. Not fun. If OTOH you had encapsulated it all in an object, you would just change the object's private implementation, keeping all accessor methods the same (e.g. getFluidVelocity(x,y,z), getPressure(x,y,z) or whatever, I'm not an engineer
It's also often useful to have data represented as objects just so you can do useful things like pass the around, build larger data structures etc. Not that you can't do this in procedural style, but OOP takes away all the pain. I've lost track of the number of times I have taken advantage of all the useful features like object serialization in Java, which saves you all the hassle of having to write import/export functions to store your data structures on disk.
Ultimately, use what seems right for your application. But remember that OOP and other techniques such as functional programming aren't just fads, they are ways to solve problems that procedural style just isn't well suited for. If you find yourself spending too much time writing the "glue" to hold a big application together, then it's a good sign that you've actually picked the wrong tool.
OOP requires a different organizational view of the problem you're working with. I've seen a tiny few people coming out of college who appear to have been introduced to the necessary concepts in college. For old school programmers or people whose degree program was still geared toward 1970s era, there's going to be a learning curve. Moreover you can't just go off on your own and start programming in C++ or Java willy nilly. You'll just reinforce bad habits while not developing any good ones. A year in a shop with good solid programmers who are willing to mentor you would probably give you a pretty good feel for what works and what doesn't. Assuming you're willing to really study the dicipline.
One of the first things your mentors will probably tell you to do is go out and get a few books. Design Patterns, Antipatterns and Refactoring books make good introductory reading. None of these things are magic bullets either, and you should refrain from viewing them a such. If you don't have Programmer Nature, none of that stuff will help you.
After all that you'll be able to write code that should be easily maintainable and flexible for new problems. Whether or not that will actually solve the problems you want solved is another question entirely.
I'm trying to teach myself to set people on fire with my mind... Is it hot in here?
The first OOP system I ever used was Digitalk's Smalltalk V, a quite successful adaptation of the ur-OO language to DOS, and later to 16-bit Windows. I was impressed by its power and expressiveness -- and frustrated by the difficulty of dealing with the huge mass of new concepts. It would have been much easier if there were a clear distinction between things I needed to know in order to extend the framework, and things I needed to know in order to create applications.
Anyone interested in OOP should download one of the many Smalltalk implementations available just to play with it. But there's a limit to the serious work you can do. There are still Smalltalk developers out there, but most people just don't have the mindset.
Modern OOP systems are mainly extensions of procedural programming languages. This disgusts OOP purists, but makes for a more shallow learning curve, and helps sharpen the distinction between features for designing objects, and features for using them.
C++ is the fanciest of these. But it's extremely complex, and should be approched slowly, if at all. C++ enthusiasts never seem to tire of finding new and obscure idioms to invent.
There are lots of OOP languages out there, but I think two recommend themselves to the newbie -- especially the newbie who wants to actually makes things. There's Java, which no longer seems likely to change the world, but is still a dominant force in some applications.
And there's Object Pascal, which outsiders consider an antiquated curiousity, but which is considered a powerful and highly usable tool by its rabid fans. OP compiles very quickly, which makes it particularly useful for RAD tools.
Which brings me to the commercial: I help document the two big Object Pascal RAD tools, Delphi (Windows), and Kylix (Linux). Both are extremely accessible to the OOP newbie, while having all the power and expressiveness of a serious OOP system. And both have versions you can download for free.
Some people down the hall do a similar tool for Java. I hear its pretty good.
First of all, for those individuals who refer to C++ as an OO language, please stop. You're wrong. C++ can be used for an OO project, but it is a multi-paradigm language. At least that's what Bjarne Stroustrup calls it. But what does he know about C++?
Second, use of C++'s STL does not equate to OO programming. It is an example of generic programming. Here's a hint: the STL has very little inheritance except for iterators and iostreams -- most evaluation is handled at compile-time. And even iterators and iostreams are just as much generic as OO.
Finally, please dispel the rumor that C is automatically faster than C++ because of C++'s excessive overhead. Need proof? Please read this article about treating C++ as its own language and not a variation of C. Yes, it's a PDF. Get over it.
Think the article is FUD? Prove it! Take the examples from the article and tune them better than he did. Compile them with trusty ol' gcc and g++ on your box. Measure the results. After you do so, can show that C is faster, does not contain any potential buffer-overflow bugs, handles error conditions, and wasn't at least five times more code to do it, then reply back with your results. I have a feeling I won't be getting any replies from people who actually try it.
That said, use whatever language you like best. Studies have shown that people will always perform better in languages they know intimately well than languages in which they have a general familiarity.
But if you want to use OO and C++, check out this numeric library
Have a nice day
- I don't need to go outside, my CRT tan'll do me just fine.
It seems you have convinced yourself that the world should be modeled in terms of procedures. This is typical for people who have programmed using procedural languages. The same happens to people who program OO: they see classes everywhere. Then you have people who like functional languages: suddenly everything seems a function.
The sad part is that all these paradigms have problems where they can be applied very well and none of them can be applied to all problems well.
Now back to OO. What is it good for: it's a good way to structure complex systems. If you have a complex system, you can probably make its structure more explicit by using objects, design patterns and so on.
Mind you, it is no silver bullet and you wouldn't be the first one to build a super complex, flexible OO everything system that doesn't perform well and is impossible to maintain.
Symptoms that indicate you might benefit from OO:
- There's a lot of commonalities between the programs you write: this indicates that you can generalize functionality.
- There's a lot of dependencies between your modules: you need to encapsulate and hide stuff
- You have a lot of complex data structures and lots of functionality around those data structures: hmm objects???
If you are serious about adopting OO you should spent some time with books about OO design such as for example Gammma's excellent book about design patterns.
As for your question regarding engineering problems. I have worked with companies involved in building embedded stuff like fire alarms, haemo dialysis machines (medical machines), mobile phones, digital radio systems and embedded server products. All of them use OO based designs to their advantage so it can be done. And in case you are wondering: all of these systems were very large systems (500 KLOC - 5 MLOC). Using OO is a necessity for these companies since it is the only tool they have to keep complexity under control.
Jilles
I haven't worked _on_ this project but I did work with it a little bit, and tried to write a small analysis routine for a class I took. Check out the OpenSEES Project at Berkeley for a good example of a OOP solution to an engineering problem. Every portion of the analysis, from equation solvers and matrix routines to structural elements and material models are broken into objects. It's an ambitious project but it's moving quickly. And it's even open source!
There is an interesting (and rather negative) review about OOP here (OOP Criticism [geocities.com]).
OOP is by no means a magic solution to programming problems.
The criticism page brought up some areas that OOP has alledged weaknesses. Many of these are highly contrived. One of these examples is the issue of mapping OOP to databases, and in particular the widely used relational database model. The problem with this particular analysis is that the mismatch occurs not due to problems in OOP, but rather with the limitations associated with mapping many types of data structures to the RDBMS model. One can hardly criticize OOP becasue it maps poorly with a technology that is far more limited than OOP is. The problem is with the RDBMS model, not OOP.
Other objections, such as data mapping from one OOP language to another are equally contrived. Already we have methodologies gaining widespread acceptance that actually do this.
The idea that OOP will fall out of favor in 15 years or so seems rather outlandish. OOP has been around for a LONG time already (LISP dates back to the mid '50s.). OOP's record of utility is well established. It's very hard to claim with a straight face that something is a fad when it in fact has been gaining acceptance and wider use over a 50 year period, spanning essentially the total time period of the development of the practice of programming.
It is true that OOP is not a magic solution to ALL programming problems. I would not use OOP in coding an FFT algorithm. However not having OOP in your toolbox markedly reduces the number of programming problems that you can map to working code in a clean, logical manner.
Sorry, but I think that's a bad example. Using an OO design has gained nothing over a simple function or two here, but has probably generated much more clutter as a result.
If I dared propose a more appropriate example in a similar vein, one thing OO is quite good at is providing and working with a representation for complicated and interrelated data items, such as a mathematical expression. Suppose I'm writing a mathematical tool to process these. I will represent an expression as an object of type Expression. Subtypes of that might be ConstantExpression (representing a numeric constant, say 2 or e), AdditionExpression (representing a+b, where a and b are themselves Expressions), etc.
Now I have a clear structure for representing these, I can parse whatever input I have into this format, and work with it. Need to display it using pretty graphics? No problem, add a Display() method to Expression's interface, and provide a suitable implementation for each subtype. Need to evaluate the expression? Eval(), here we come.
So far, so good. You've used OO to provide a nice representation of a problem, at least as clearly as a procedural solution would have done. It's pretty much a draw so far, and a matter of personal preference which style you prefer.
However, the OO framework is much more easily extensible than its procedural counterpart. You can add new subtypes of Expression, and have them immediately fit into your existing framework, without changing any of your existing code (or even having access to it, for that matter). To do this procedurally, you often wind up writing some clever switching logic, but OO does it all for you behind the scenes.
It's also easier for the outside world to work with your code, because you can provide nice, clean interfaces, such that all Expressions look the same to the outside world, however they are composed.
Finally, this approach helps organise your code. If all your types of Expression provide an Eval() interface, the implementation of that interface is in a known place, and probably quite straightforward for each subtype. This maintains a degree of clarity that is easily lost when you don't have the organisational framework an OO design supports.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
One of the most common misconceptions in the industry is that C++ is 'an OOP language.' For that matter, it is similiarly incorrect to label C a procedural language. Paradigms like Object Oriented or Procedural are exactly that
The first C++ compilers were merely front ends for C ones, which took C++ constructs and generated C code, which was then compiled and linked into an executable. It is true that C++ was developed to assist in making OOP constructs with clarity and ease (let's not argue the success or lack therof here, please.) Still, nothing stops one from OOP modelling in Assembly Language and procedural was always openly supported by Bjarne Stroustrup when he invented C++.
You call the problem on the head when you say "I cannot, however, convince myself that there is a clean way to use these concepts to solve the type of procedural problems that I have encountered in the past." When your problems lend themselves to procedural solutions then you want to think about them that way, just as when your problems lend themselves to Object Oriented models, you want to model them that way.
The right tool for the right job. If you want to implemet a Fast Fourier Transform you want to look at it procedurally. If you want to model a Robot, in which thousands of components performing those FFTs interact, you probably want to take your procedural code, wrap it in some Object Oriented code, and get your model.
OOP and Procedural are complementary analytical methods, not competitors. It is an abuse on the part of any software engineer to view or discuss them otherwise!
Guns don't kill people; Physics kills people! - John Lithgow as Dick Solomon on Third Rock From The Sun
One way of looking at software engineering divides it into levels of abstraction at which people work. In the traditional view, engineering proceeded by starting at the highest level and proceeding in a orderly manner towards code. We're coming to realise that approach is wrong, but the levels of abstraction still exist. You can use OO at all these levels, by modelling things in terms of classes.
At the highest level, often called analysis, classes, objects and the relationships between them should correspond to concepts in the problem domain. Implementation issues should not come into it. An analysis model should end up representing the system as the user thinks about it.
At the code level, objects are indeed methods combined with data, but while the analysis model won't have captured all, or even most, of the code you end up writing, the concepts in it should still be present in the code.
Encapsulation is only half the story. To get any benefit from OO, polymorphism is essential. Encapsulation does indeed get you nice organisation by itself, but you don't get any improvement of flexibility. With polymorphism added, you gain the vital ability to operate on objects without having to discover their runtime type. This lets you write, for instance, a catalogue system that can operate on video tapes or books, without having to have any knowledge of what exactly its working on.
This is an oft-cited anti-OO article. However, it's clearly written by a very biased author, is hardly objective (no pun intended) and is littered with obvious misunderstandings about OO.
Rather than spend hours dismantling his major arguments and point out all the flaws, I'll just post his "challenge" to the OO community to prove the superiority of OO:
Now tell me, how many people are going to expend the dozens of hours probably required to fulfil this challenge, and then field an arbitrary number of arbitrary questions from the author as a result? Is this a reasonable challenge? Does he seriously expect anyone to take it up in earnest?
Note also the rather gratuitous disclaimer, waaaay down (probably off most people's screens) on the front page of a whole anti-OO site:
'Nuff said, I think.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
Yep, some of us are still slogging on, writing our MLOC projects in C++; there's no reason for us not to.
The thing is, we use C++ in a smart way. You keep the low level stuff at low levels, instead of polluting your whole code base with it. That immediately kills most anti-C++ "it's not safe" arguments. You then write mid level building blocks from the low level stuff, and you write high level code using those building blocks. Most of the code we write today uses concepts every bit as high level as most other mainstream languages, often more so, because we use the tools for abstraction that C++ provides appropriately.
IME, the reason many people give up on C++, and switch to "higher level" languages, is that they've never really understood the abstraction tools in C++, and have always just used it as a "better C" with a few objects around in a badly designed hierarchy. Our friends over at MS showed the world how not to do it when they designed (and I use the term loosely) the MFC, which is a thin wrapper around C code, and not a proper OO framework at all.
If a few more programmers went out and learned their craft, instead of trying to use a powerful tool like C++ without learning the ropes first (but it's OK, they program C, so they don't need any more training to know C++) then fewer of them would decide that "C++ sux" and run away.
Of course, the target audience for C++ is, and really always has been, the programmers at the top who are prepared to make the effort to learn to use it. Those who do, reap the rewards, and find many "higher level languages" horribly limited in comparison.
Just MHO, of course, but I've certainly seen it often enough to be sure of that opinion.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
I read it, and gave up partway through the discussion, because most of the comments made were so much ill-informed FUD that it actually made me angry. It's true that C++'s biggest problem is the ignorance of the programming community, but I had hoped for better from the /. community until I read that discussion.
The extra overhead involved in initialising objects in C++ is similar in both purpose and time consumption to the overhead when you first load a C program. It may take marginally longer, but it's measured in milliseconds, and a one-off when you first start up. It's one of the few places where C++ can genuinely be slower than C, and it's still hardly worth mentioning.
I really hope your perspective isn't based on articles like that. It's well-meant, I'm sure, but there was never any debate about whether C++ was slower than C in informed circles, because the answer is obvious: no. Whether you look at the theory of the languages (try reading The Design and Evolution of C++, by Bjarne Stroustrup for some insights) or simply code generated from C++ and the equivalent functionality in C, you find the two comparable on all counts. There is far more variability in quality between compilers of either language than there is between the two languages. In fact, some language features allow C++ to make optimisations C couldn't even dream of, bettering it several fold in performance.
ROFLMAO. I'm sorry, but this is just not carrying any weight with me. Let's look at a few quotes from the first couple of pages, and see how the author demonstrates a lack of consideration on his part, not that of the group behind C++.
No, that is exactly the wrong decision. These are not fundamental features in a language with low level support. Much better to provide a simple language with solid foundations, and build a powerful library on top, than to clutter a language with "powerful" features, but then find the next time you need a new powerful feature, you have to change everything around, or can't add it at all. These features are still available in C++; what difference does it make to the developer whether they are built in or part of a standard library?
And yet, many languages (not just C++) implement MI quite happily, in various ways, with good efficiency and few bugs. Speaking as someone who uses this feature on a regular basis in large application frameworks, I can say with some authority that it's rarely appropriate, but when it is, it's horrible to be without it. Supporting interface inheritance alone is not an adequate solution to replace many useful MI idioms, however much those without MI like to claim otherwise.
And how exactly were you planning to write useful generic algorithms without this? Many critics slam op overloading, and many of the same advocate the introduction of generics into their language of choice. Few have thought it through enough to see the connection. Again, C++ got this one right.
Riiiight. So we're going to improve on C++ by removing the ability to write classes with value semantics, or indeed programmer-definable semantics at all. Further, we're going to be replacing the powerful RAII idiom with the rather underpowered and error-prone try-finally construct. And this is progress?
Unless you're going to provide a smart alternative, you just hit your performance big-time. In doing things like this, you cripple your language for developing truly high performance apps.
OK, let's rule out writing for embedded systems completely as well.
I could go on, and dismantle many of the other myths, personal views that are far from universal and downright misleading claims on the site, but I don't see much point. There are certainly flaws in C++ -- some of which will be addressed in the next revision -- but things like having MI and op overloading are not among them. Putting C++ down on that basis, in the face of informed opposition, just makes you look like you haven't done your homework.
You know, the best bit of that page is the "Who D Is For" bit. I guess I qualify, as do many I have worked with, on about 75% of those counts. Yet the arguments given in the previous "Features To Drop" section would immediately convince me that D wasn't a serious tool.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.