Related
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I have been asked to begin teaching C# and OO concepts to a group of procedural programmers. I've searched for ideas on where to begin, but am looking for general consensus on topics to lead with in addition to topics to initially avoid.
Edit
I intend to present information in 30 minute installments weekly until it no longer makes sense to meet. These presentations are targeted at coworkers at a variety of skill levels from novice to expert.
The best thing you can do is: Have a ton of Q&A.
Wikipedia's procedural programming (PP) article really hits where you should start:
Whereas procedural programming uses
procedures to operate on data
structures, object-oriented
programming bundles the two together
so an "object" operates on its "own"
data structure.
Once this is understood, I think a lot will fall into place.
In general
OOP is one of those things that can take time to "get," and each person takes their own path to get there. When writing in C#, it's not like the code screams, "I am using OO principles!" in every line. It's more of a subtle thing, like a foreach loop, or string concatenation.
Design center
Always use something (repeatedly) before making it.
First, use an object, and demonstrate the basic differences from PP. Like:
static void Main(string[] args)
{
List<int> myList = new List<int>();
myList.Add(1);
myList.Add(7);
myList.Add(5);
myList.Sort();
for (int i = 0; i < myList.Count; i++)
{
Console.WriteLine(myList[i]);
}
}
Using objects (and other OO things) first -- before being forced to create their own -- leads people down the path of, "Ok, I'm making something like what I just used," rather than "WTF am I typing?"
Inheritance (it's a trap!)
I would NOT spend a lot of time on inheritance. I think it is a common pitfall for lessons to make a big deal about this (usually making a cliché animal hierarchy, as others pointed out). I think it's critical to know about inheritance, to understand how to use the .NET Framework, but its nuances aren't that big of a deal.
When I'm using .NET, I'm more likely to "run into inheritance" when I'm using the .NET Framework (i.e. "Does this control have a Content property?" or "I'll just call its ToString() method.") rather than when I'm creating my own class. Very (very (very)) rarely do I feel the need to make something mimicking the taxonomy structure of the animal kingdom.
Interfaces
Coding to an interface is a key mid-level concept. It's used everywhere, and OOP makes it easier. Examples of this are limitless. Building off the example I have above, one could demonstrate the IComparer<int> interface:
public int Compare(int x, int y)
{
return y.CompareTo(x);
}
Then, use it to change the sort order of the list, via myList.Sort(this). (After talking about this, of course.)
Best practices
Since there are some experienced developers in the group, one strategy in the mid-level classes would be to show how various best practices work in C#. Like, information hiding, the observer pattern, etc.
Have a ton of Q&A
Again, everyone learns slightly differently. I think the best thing you can do is have a ton of Q&A and encourage others in the group to have a discussion. People generally learn more when they're involved, and you have a good situation where that should be easier.
The leap from procedural to object oriented (even within a language - for four months I programmed procedural C++, and classes were uncomfortable for a while after) can be eased if you emphasize the more basic concepts that people don't emphasize.
For instance, when I first learned OOP, none of the books emphasized that each object has its own set of data members. I was trying to write classes for input validation and the like, not understanding that classes were to operate on data members, not input.
Get started with data structures right away. They make the OOP paradigm seem useful. People teach you how to make a "House" class, but since most beginning programmers want to do something useful right away, that seems like a useless detour.
Avoid polymorphism right away. Inheritance is alright, but teach when it is appropriate (instead of just adding to your base class).
Operator overloading is not essential when you are first learning, and the special ctors (default, dtor, copy ctor, and assignment operator all have their tricky aspects, and you might want to avoid that until they are grounded in basic class design).
Have them build a Stack or a Linked List. Don't do anything where traversal is tricky, like a binary tree.
Do it in stages.
High level concepts : Describe what an object is and relate it to real life.
Medium level concepts: Now that they got what object is, try compare and contrast. Show them why global variable is bad compared to an encapsulated value in a class. What advantage they might get from encapsulating. Start introducing the tennets of OOP (encapsulation, inheritance)
Low Level concepts: Go in further into polymorphism and abstraction. Show them how they can gain even better design through polymorphism and abstraction.
Advance concepts: SOLID, Interface programming, OO design patterns.
Perhaps you should consider a problem that is work related and start with a procedural implementation of it and then work through (session by session) how to make an OOP implementation of it. I find professionals often grasp concepts better if it is directly related to real examples from their own work place. The junk examples most textbooks use are often horrible for understanding because they leave the student wondering, why on earth would I ever want to do that. Give them a real life reason why they would want to do that and it makes more sense.
I would avoid the "a bicycle is a kind of veichle" approach and try to apply OO to an environment that is fairly specific and that they are already used to. Try to find a domain of problems that they all recognize.
Excercise the basics in that domain, but try to move towards some "wow!" or "aha!" experience relatively early; I had an experience like that while reading about "Replace Conditional with Polymorphism" in Fowlers Refactoring, that or similar books could be a good source of ideas. If I recall correctly, Michael Feathers Working effectively with legacy code contains a chapter about how to transform a procedural program into OO.
Teach Refactoring
Teach the basics, the bare minimum of OO principles, then teach Refactoring hands-on.
Traditional Way: Abstractions > Jargon Cloud > Trivial Implementation > Practical Use
(Can you spot the disconnect here? One of these transitions is harder than the others.)
In my experience most traditional education does not do a good job in getting programmers to actually grok OO principles. Instead they learn a bit of the syntax, some jargon they have a vague understanding of, and a couple canonical design examples that serve as templates for a lot of what they do. This is light years from the sort of thorough understanding of OO design and engineering one would desire competent students to obtain. The result tends to be that code gets broken down into large chunks in what might best be described as object-libraries, and the code is nominally attached to objects and classes but is very, very far from optimal. It's exceedingly common, for example, to see several hundred line methods, which is not very OO at all.
Provide Contrast To Sharpen The Focus on the Value of OO
Teach students by giving them the tools up front to improve the OO design of existing code, through refactoring. Take a big swath of procedural code, use extract method a bunch of times using meaningful method names, determine groups of methods that share a commonality and port them off to their own class. Replace switch/cases with polymorphism. Etc. The advantages of this are many. It gives students experience in reading and working with existing code, a key skill. It gives a more thorough understanding of the details and advantages of OO design. It's difficult to appreciate the merits of a particular OO design pattern in vacuo, but comparing it to a more procedural style or a clumsier OO design puts those merits in sharp contrast.
Build Knowledge Through Mental Models and Expressive Terminology
The language and terminology of refactoring help students in understanding OO design, how to judge the quality of OO designs and implementations through the idea of code smells. It also provides students a framework with which to discuss OO concepts with their peers. Without the models and terminology of, say, an automobile transmission, mechanics would have a difficult time communicating with each other and understanding automobiles. The same applies to OO design and software engineering. Refactoring provides abundant terminology and mental models (design patterns, code smells and corresponding favored specific refactorings, etc.) for the components and techniques of software engineering.
Build an Ethic of Craftsmanship
By teaching students that design is not set in stone you bolster students' confidence in their ability to experiment, learn, and discover. By getting their hands dirty they'll feel more empowered in tackling software engineering problems. This confidence and practical skill will allow them to truly own the design of their work (because they will always have the skills and experience to change that design, if they desire). This ownership will hopefully help foster a sense of responsibility, pride, and craftsmanship.
First, pick a language like C# or Java and have plenty of samples to demonstrate. Always show them the big picture or the big idea before getting into the finer details of OO concepts like abstraction or encapsulation. Be prepared to answer a lot of why questions with sufficient real world examples.
I'm kinda surprised there's any pure procedural programmers left ;-)
But, as someone who started coding back in the early 80s on procedural languages such as COBOL, C and FORTRAN, I remember the thing I had most difficulty with was instantiation. The concept of an object itself wasn't that hard as basically they are 'structures with attached methods' (looked at from a procedural perspective) but handling how and when I instantiated an object - and in those days without garbage collection - destroyed them caused me some trouble.
I think this arises because in some sense a procedural programmer can generally point to any variable in his code any say that's where that item of data is directly stored, whereas as soon as you instantiated an object and assign values to that then it's much less directly tangible (using pointers and memory allocation in C is of course similar, which may be a useful starting point also if your students have C experience). In essence I suppose it means that your procedural -> OOPS programmer has to learn to handle another level of abstraction in their code, and getting comfortable with this mental step is more difficult than it appears. By extension I'd therefore make sure that your students are completely comfortable with allocating and handling objects before looking at such potentially confusing concepts as static methods.
I'd recommend taking a look at Head First Design Patterns which has really nice and easy to understand examples of object oriented design which should really help. I wouldn't emphasize the 'patterns' aspect too much at this point though.
I'm a vb.net intermediate programmer, and I'm learning OOP. One of the things I find is the lecturing about the concepts over and over is unnerving. I think what would be perfect documentation would be a gradual transition from procedural programming to full blown OOP rather than trying to force them to understand the concepts then have them write exclusively OOP code using all the concepts. That way they can tinker with little projects like "hello world" without the intimidation of design.
For example (this is for VB.NET beginners not advanced procedural programmers).
I think the first chapters should always be about the general concepts, with just a few examples, but you should not force them to code strictly OOP right away, get them used to the language, so that it's natural for them. When I first started, I had to go back and read the manual over and over to remember HOW to write the code, but I had to wade through pages and pages of lecturing about concepts. Painful!
I just need to remember how to create a ReadOnly Property, or something. What would be real handy would be a section of the book that is a language reference so you can easily look in there to find out HOW to write the code.
Then you briefly explaining how forms, and all the objects are already objects, that have methods, and show how they behave, and example code.
Then show them how to create a class, and have them create a class that has properties, and methods, and the new construct. Then have them basically switch from them using procedural code in the form or modules, to writing methods for classes.
Then you just introduce more advance codes as you would any programming language.
Show them how inheritance works, etc. Just keep expanding, and let them use thier creativity to discover what can be done.
After they get used to writing and using classes, then show how thier classes could improve, introducing the concepts one by one in the code, modifying the existing projects and making them better. One good idea is to take an example project in procedural code, and transform it into a better application in OOP showing them all the limitations of OOP.
Now after that is the advanced part where you get into some really advanced OOP concepts, so that folks who are familar with OOP already get some value out of the book.
Define an object first, not using some silly animal, shape, vehicle example, but with something they already know. The C stdio library and the FILE structure. It's used as an opaque data structure with defined functions. Map that from a procedural use to an OO usage and go from there to encapsulation, polymorphism, etc.
If they are good procedural programmers and know what a structure and a pointer to a function are, the hardest part of the job is already done!
I think a low level lecture about how Object Oriented Programming can be implemented in procedural languages, or even assembler, could be cool. Then they will appreciate the amount of work that the compiler does for them; and maybe they will find coding patterns that they already knew and have used previously.
Then, you can talk about best practices in good Object Oriented design and introduce a bit of UML.
And a very important thing to keep in mind always is that they're not freshmen, don't spend much time with basic things because they'll get bored.
Show Design Patterns in Examples
There where some plenty good answers, alright. I also think, that you should use good languages, good, skillful examples, but I have an additional suggestion:
I have learned what OOP means, by studying Design Patterns. Of course, I have of course learned an OO-language before, but until I was working on Design Patterns, I did not understand the power of it all.
I also learned much from OO-Gurus like Robert C. Martin and his really great papers (to be found on his companies site).
Edit: I also advocate the use of UML (class diagrams) for teaching OO/Design-Pattern.
The thing that made it click for me was introducing Refactoring and Unit Testing. Most of my professional programming career has been in OO Languages, but I spent most of it writing procedural code. You call a function on an instance of class X, and it called a different method on an instance of class Y. I didn't see what the big deal about interfaces was, and thought that inheritance was simply a concept of convenience, and classes were by and large a way of helping us sort and categorize the massive code. If one was masochistic enough, they could have easily go through some of my old projects and inline everything until you get to one massive class. I'm still acutely embarrassed at how bad my code was, how naive my architecture was.
It half-clicked when we went through Martin Fowler's Refactoring book, and then fully clicked when started going through and writing Unit and Fitnesse tests for our code, forcing us to refactor. Start pushing refactoring, dependency injection, and separation of the code into distinct MVC models. Either it will sink in, or their heads will explode.
If someone truly doesn't get it, maybe they aren't cut out for working on OO, but I don't think anyone from our team got completely lost, so hopefully you'll have the same luck.
I'm an OO developer professionally, but have had had procedural developers on my development team (they were developing Matlab code, so it worked). One of the concepts that I like in OO programming is how objects can relate to your domain (http://en.wikipedia.org/wiki/Domain-driven_design - Eric Evans wrote a book on this, but it is not a beginner's book by any stretch).
With that said, I would start with showing OO concepts at a high level. Try to have them design a car for example. Most people would say a car has a body, engine, wheels, etc. Explain how those can relate to real world objects.
Once they seem to grasp that high level concept, then I would start in on the actual code part of it and concepts like inheritance vs aggregation, polymorphism, etc.
I learned about OOP during my post-secondary education. They did a fairly good job of explaining the concepts, but completely failed in explaining why and when. They way they taught OOP was that absolutely everything had to be an object and procedural programming was evil for some reason. The examples they were giving us seemed overkill to me, partly because objects didn't seem like the right solution to every problem, and partly because it seemed like a lot of unnecessary overhead. It made me despise OOP.
In the years since then, I've grown to like OOP in situations where it makes sense to me. The best example I can think of this is the most recent web app I wrote. Initially it ran off a single database of its own, but during development I decided to have it hook into another database to import information about new users so that I could have the application set them up automatically (enter employee ID, retrieves name and department). Each database had a collection of functions that retrieved data, and they depended on a database connection. Also, I wanted an obvious distinction which database a function belonged to. To me, it made sense to create an object for each database. The constructors did the preliminary work of setting up the connections.
Within each object, things are pretty much procedural. For example, each class has a function called getEmployeeName() which returns a string. At this point I don't see a need to create an Employee object and retrieve the name as a property. An object might make more sense if I needed to retrieve several pieces of data about an employee, but for the small amount of stuff I needed it didn't seem worth it.
Cost. Explain how when properly used the features of the language should allow software to be written and maintained for a lower cost. (e.g. Java's Foo.getBar() instead of the foo->bar so often seen in C/C++ code).Otherwise why are we doing it?
I found the book Concepts, Techniques, and Models of Computer Programming to be very helpful in understanding and giving me a vocabulary to discuss the differences in language paradigms. The book doesn't really cover Java or C# as 00-languages, but rather the concepts of different paradigms. If i was teaching OO i would start by showing the differences in the paradigms, then slowly the differences in the 00-languages, the practical stuff they can pickup by themselves doing coursework/projects.
When I moved from procedural to object oriented, the first thing I did was get familiarized with static scope.
Java is a good language to start doing OO in because it attempts to stay true to all the different OO paradigms.
A procedural programmer will look for things like program entry and exit points and once they can conceptualize that static scope on a throwaway class is the most familiar thing to them, the knowledge will blossom out from there.
I remember the lightbulb moment quite vividly. Help them understand the key terms abstract, instance, static, methods and you're probably going to give them the tools to learn better moving forward.
As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
I asked a question previously about Dataset vs Business Objects
.NET Dataset vs Business Object : Why the debate? Why not combine the two?
and I want to generalize the question here: where is the proof that OOP is really suitable for very complex problems ? Let's take a MMO Game Engine for example. I'm not specialist at all but as I read this article, it clearly stands that OOP is far from being enough:
http://t-machine.org/index.php/2007/11/11/entity-systems-are-the-future-of-mmog-development-part-2/
It concludes:
Programming well with Entity Systems is very close to programming with a Relational Database. It would not be unreasonable to call ES’s a form of “Relation Oriented Programming”.
So isn't OOP trying to get rid off something that is here to stay ?
OOP is non-linear, Relational is linear, both are necessary depending on the part of a system so why try to eliminate Relational just because it isn't "pure" Object. Is OOP an end by itself ?
My question is not is OOP usefull. OOP is usefull, my question is rather why the purists want to do "pure" OOP ?
As the author of the linked post, I thought I'd throw in a couple of thoughts.
FYI: I started seriously (i.e. for commercial work) using OOP / ORM / UML in 1997, and it took me about 5 years of day to day usage to get really good at it IMHO. I'd been programming in ASM and non-OOP languages for about 5 years by that point.
The question may be imperfectly phrased, but I think it's a good question to be asking yourself and investigating - once you understand how to phrase it better, you'll have learnt a lot useful about how this all hangs together.
"So isn't OOP trying to get rid off something that is here to stay ?"
First, read Bjarne's paper here: http://www.stroustrup.com/oopsla.pdf
IMHO, no-one should be taught any OOP without reading that paper (and re-reading after they've "learnt" OOP). So many many people misunderstand what they're dealing with.
IME, many university courses don't teach OOP well; they teach people how to write methods, and classes, and how to use objects. They teach poorly why you would do these things, where the ideas come from, etc. I think much of the mis-usage comes from that: almost a case of the blind leading the blind (they aren't blind in "how" to use OOP, they're just blind in "why" to use OOP).
To quote from the final paragraphs of the paper:
"how you support good programming techniques and good design techniques matters more than labels and buzz words. The fundamental idea is simply to improve design and programming through abstraction. You want to hide details, you want to exploit any commonality in a system, and you want to make this affordable.
I would like to encourage you not to make object-oriented a meaningless term. The notion of ‘‘object-oriented’’ is too frequently debased:
– by equating it with good,
– by equating it with a single language, or
– by accepting everything as object-oriented.
I have argued that there are–and must be–useful techniques beyond object-oriented programming and design. However, to avoid being totally misunderstood, I would like to emphasize that I wouldn’t attempt a serious project using a programming lan-
guage that didn’t at least support the classical notion of object-oriented programming. In addition to facilities that support object-oriented programming, I want –and C++ provides features that go beyond those in their support for direct expression of concepts and relationships."
Now ... I'd ask you ... of all the OOP programmers and OOP projects you've seen, how many of them can honestly claim to have adhered to what Bjarne requests there?
IME, less than the majority.
Bjarne states that:
"The fundamental idea is simply to improve design and programming through abstraction"
...and yet many people invent for themselves a different meaning, something like:
"The fundamental idea is that OOP is good, and everything-not-OOP is inferior"
Programmers who have programmed sequentially with ASM, then later ASM's, then pascal, then C, then C++, and have been exposed to the chaos that was programming pre-encapsulation etc tend to have better understanding of this stuff. They know why OOP came about, what it was trying to solve.
Funnily enough, OOP was not trying to solve every programming problem. Who'd have htought it, to say how it's talked about today?
It was aimed at a small number of problems that were hugely dangerous the bigger your project got, and which it turned out to be somewhere between "good" and "very good" at solving.
But even some of them it isn't any better than merely "good" at solving; there are other paradigms that are better...
All IMHO, of course ;)
Systems of any notable complexity are not linear. Even if you worked really hard to make a system one linear process, you're still relying on things like disks, memory and network connections that can be flaky, so you'll need to work around that.
I don't know that anyone thinks OOP is the final answer. It's just a way of dealing with complexity by trying to keep various problems confined to the smallest possible sphere so the damage they do when they blow up is minimized. My problem with your question is that it assumes perfection is possible. If it were, I could agree OOP isn't necessary. It is for me until someone comes up with a better way for me to minimize the number of mistakes I make.
Just read yr article about Entity Systems, which compares ES to OOP, and it is flagrantly wrong about several aspects of OOP. for e.g., When there are 100 instances of a class, OOP does not mandate that there be 100 copies of the classes methods loaded in memory, only one is necessary. Everything that ES purports to be able to do "better" than OOP because it has "Components", and "Systems", OOP supports as well using interfaces and static classes, (and/or Singletons).
And OOP more naturally fits with the real-world, as any real or imagined Problem Domain, consisting of multiple physical and/or non-physical items and abstractions, and the relationships between them, can be modeled with an appropriately designed hiearchical OOP class structure.
What we try to do is put an OO style on top of a relational system. In C# land this gets us a strongly typed system so that everything from end to end can be compiled and tested. The database has a hard time being tested, refactored, etc. OOP allows us to organize our application into layers and hiearchies which relational doesn't allow.
Well you've got a theoretical question.
Firstly let me agree with you that OOP is not a solve-all solution. It's good for somethings, it's not good for others. But that doesn't mean it doesn't scale up. Some horribly complex and huge systems have been designed using OOP.
I think OOP is so popular because it deserves to be. It solves some problems rather wonderfully, it is easy to think in terms of Objects because we can do that without re-programming ourselves.
So until we can all come up with a better alternatives that actually works in practical life, I think OOP is a pretty good idea and so are relational databases.
There is really no limit to what OOP can deal with - just as there is no real limit to what C can deal with, or assembler for that matter. All are Turing-complete, which is all you really need.
OOP simply gives you a higher-level way of breaking down the program, just as C is a higher-level than assembler.
The article about entity systems does not say that OO cannot do this - in fact, it sounds like they are using OOP to implement their Entities, Components, etc. In any complex domain there will be different ways of breaking it down, and using OOP you can break it down to the object/class level at some point. This does not preclude having higher-level conceptual frameworks which are used to design the OOP system.
The problem isn't the object oriented approach in most situations, the problem is performance and actual development of the underlying hardware.
The OO paradigm approach software development by providing us with a metaphor of the real world, were we have concepts which defines the common accepted and expected properties and behaivour of real objects in the world. Is the way that humans model things and we're able to solve most of the problems with it.
In theory you can define every aspect of a game, system or whatever using OO. In practice if you do, your program will simply behave too slow so the paradigm is messed up by optimizations which trade the simplicity of the model from performance.
In that way, relational databases are not object oriented so we build an object oriented layer between our code and the database... by doing so you lost some of the performance of the database and some of its expressiveness because, from the point of view of OO paradigm a relational database is a full class, is an very complex object that provides information.
From my point of view OO is an almost perfect approach in the theoretical sense of the word, as it maps closely to the way we, humans, think, but it doesn't fit well with the limited resources of the computational development... so we take shortcuts. At the and, performance is far more important than theoretical organization or clearness so this shortcuts become standards or usual practices.
That is, we are adapting the theoretical model to our current limitations. In the times of cobol in the late 70's object oriented was simply impossible... it would imply to many aspects and too little performance so we used a simplified approach, so simplified you didn't have objects or class, you had variables ... but the concept was, in that time, the same. Groups of variables described related concepts, properties that today will feet into an object. Control sequences based on a variable value where used to replace class hierarchies and so on.
I think we've been using OOP for a long time and that we'll continue using it for a long time. As hardware capabilities improve we'll be able to unsimplify the model so that it becomes more adaptable. If I describe perfectly (almost) the concept of a cat (which involves a lot of describing for a lot of concepts involved) that concept will be able to be reused everywhere... the problem here is not, as I've said, with the paradigm itself but with our limitations to implement it.
EDIT: To answer the question about why use pure OO. Every "science" wants to have a complete model to represent things. We have two physic models to describe nature, one at the microscopic level and one for the macroscopic one, and we want to have just one because it simplifies things it provides us with a better way to prove, test and develop things. With OO the same process applies. You can't analytically test and prove a system if the system doesn't follow a precise set of rules. If you are changing between paradigms in a program then your program cannot be properly analized, it has to be disected in each one, analized and then analized again to see that the interactions are correct. It makes a lot more difficult to understand a system because in fact you have two or three system that interact in different ways.
Guys, isn't the question more about ORM than OOP? OOP is a style of programming - the thing that actually gets compared is a Relational Database mapped onto objects.
OOP is actually more than just the ORM! It's also not just the inheritance and polymorphism! It's an extremly wide range of design patterns and above all it's the way we think about programming itself.
Jorge: it's ok that you've pointed out the opitimization part - what you didn't add is that this step should be done last and in 99% cases the slow part is not the OOP.
Now plain and simple: the OOP style with all the principals added to it (clean code, use of design patterns, not to deep inheritance structures and let's not forget unit testing!) it a way to make more people understand what you wrote. That in turn is needed for companies to keep their bussiness secure. That's also a recepie for small teams to have better understanding with the community. It's like a common meta language on top of the programming language itself.
It's always easier to talk about concepts from a purists point of view. Once you're faced with a real life problem things get trickier and the world is no longer just black and white. Just like the author of the article is very thorough in pointing out that they're not doing OOP the "OOP purist" tells you that OOP is the only way to go. The truth is somewhere in between.
There is no single answer, as long as you understand the different ways (OOP, entity systems, functional programming and many more) of doing things and can give good reason for why you're choosing one over the other in any given situation you're more likely to succeed.
About Entity Systems. It's an interesting conception but it brings nothing really new. For example it states:
OOP style would be for each Component to have zero or more methods, that some external thing has to invoke at some point. ES style is for each Component to have no methods but instead for the continuously running system to run it’s own internal methods against different Components one at a time.
But isn't it same as Martin Fowler's anti-pattern called "Anemic Domain Model" (which is extensively used nowadays, in fact) link ?
So basically ES is an "idea on the paper". For people to accept it, it MUST be proven with working code examples. There is not a single word in the article on how to implement this idea on practice. Nothing said about scalability concerns. Nothing said about fault tolerance...
As for your actual question I don't see how Entity Systems described in article can be similar to relational databases. Relational databases have no such thing as "aspects" that are described in the article. In fact, relational - based on tables data structure - is very limited when it comes to working with hierarchical data, for example. More limited than for example object databases...
Could you clarify what exactly you are trying to compare and prove here? OOP is a programming paradigm, one of the many. It's not perfect. It's not a silver bullet.
What does "Relation Oriented Programming" mean? Data-centric? Well, Microsoft was moving towards more data-centric style of programming until they given up on Linq2Sql and fully focused on their O/RM EntityFramework.
Also relational databases isn't everything. There is many different kinds of database architectures: hierarchical databases, network databases, object databases ect. And those can be even more efficient than relational. Relational are so popular for nearly the same reasons why OOP is so popular: it's simple, very easy to understand and most often efficient enough.
Ironically when oo programming arrived made it much easier to build larger systems, this was reflected in the ramp up in software to market.
Regarding scale and complexity, with good design you can build pretty complex systems.
see ddd Eric Evans for some principle patterns on handling complexity in oo.
However not all problem domains are best suited to all languages, if you have the freedom to choose a language choose one that suits your problem domain. or build a dsl if that's more appropriate.
We are software engineers after all, unless there is someone telling you how to do your job, just use the best tools for the job, or write them :)
I've worked with designing databases for a loooong time, and these days I'm working in C# too. OO makes sense to me, but I don't feel that I have a good grounding in the deep theory of OO design.
In database land, there's a lot of theory around how to design the structure of a database, the main notion being normalisation. Normalisation directly steers the structure of a database and to some extent dictates how to arrange entities in a database.
Are there any similar concepts behind how to design the structure of an Object-Oriented program?
What I'm reaching for is one or more underlying theoretical principles which naturally guide the developer into the "correct" design for the solution to a given problem.
Where can I look to find out more?
Is there a go-to work I should read?
Update:
Thanks to everyone for their answers.
What I'm reading seems to say that there is no "Grand Theory of OO Design", but there are a bunch of important principles - which are largely exemplified by design patterns.
Thanks again for your answers :)
Be careful some of the design patterns literature.
There are are several broad species of class definitions. Classes for persistent objects (which are like rows in relational tables) and collections (which are like the tables themselves) are one thing.
Some of the "Gang of Four" design patterns are more applicable to active, application objects, and less applicable to persistent objects. While you wrestle through something like Abstract Factory, you'll be missing some key points of OO design as it applies to persistent objects.
The Object Mentor What is Object-Oriented Design? page has mich of you really need to know to transition from relational design to OO design.
Normalization, BTW, isn't a blanket design principle that always applies to relational databases. Normalization applies when you have update transactions, to prevent update anomalies. It's a hack because relational databases are passive things; you either have to add processing (like methods in a class) or you have to pass a bunch of rules (normalization). In the data warehouse world, where updates are rare (or non-existent) that standard normalization rules aren't as relevant.
Consequently, there's no "normalize like this" for object data models.
In OO Design, perhaps the most important rule for designing persistent objects is the Single Responsibility Principle.
If you design your classes to have good fidelity to real-world objects, and you allocate responsibilities to those classes in a very focused way, you'll be happy with your object model. You'll be able to map it to a relational database with relatively few complexities.
Turns out, that when you look at things from a responsibility point of view, you find that 2NF and 3NF rules fit with sound responsibility assignment. Unique keys still matter. And derived data becomes the responsibility of a method function, not a persistent attribute.
The book "Design Patterns" is your next step.
http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612
But, you don't have to use an OO approach to everything. Don't be religious about it. If a more procedural approach feels more straitforward, then go with that. People new to OO tend to overdue it for a while.
I think Agile Software Development, Principles, Patterns, and Practices is quite good.
It provides a lot of in-depth disccusion of OO principles listed here:
The principles of Object Oriented Design and Dependency Management
SRP — The Single Responsibility Principle
OCP — The Open Closed Principle
LSP — The Liskov Substitution Principle
DIP — The Dependency Inversion Principle
ISP — The Interface Segregation Principle
REP — The Reuse Release Equivalency Principle
CCP — The Common Closure Principle
CRP — The Common Reuse Principle
ADP — The Acyclic Dependencies Principle
SDP — The Stable Dependencies Principle
SAP — The Stable Abstractions Principle
If you're used to building normalized databases, then Object Oriented design should come naturally to you. Your class structures will end up looking a lot like your data structure, with the obvious exception that association tables turn into lists and lookup tables turn into enums within your classes.
All together, I'd say you're a lot better off coming into OO design with a background in Relational Databases than you would be going the other direction.
If you want to really get to grips with O-O, go play with Smalltalk. ST is a pure OO language, and quite in-your-face about it. Once you get over the paradigm hump you've learned OO as you can't really do Smalltalk without it. This is how I first learned OO.
Check the results of this. Learn from each question.
I really liked Head First Design Patterns, which is very approachable, and the excellent Object oriented Design Heuristics by Arthur J. Riel
This site lists 101 title... design patterns, refactoring and other... Have a look at it.. It will be a good starting point...
Go for Object Thinking by David West. An interesting read..
You're from the dark side though.. as per the book;) Database thinking has been the curse of OO programmers all over. They're opposite ends of a spectrum. For instance
Database thinking values the data attribues over everything else.. normalization and creating types based on how they fit into the DB Schema OR the ER diagram.. OO thinking creates types based on behavior and collaboration and does not recognize the data attributes as all important.
Databases come from the scientific people who value formalization and method over everything else. OO comes from the people who use heuristics and rules of thumb and value individuality and social interaction over a hard and fast process.
The point being a COBOL programmer can write COBOL programs even after moving onto a OO Language. Check out any book like Thinking in Java for the first section which invariably details out the tenets of OO (Apprentice).. Follow it up with Object Thinking (journeyman) and in due time.. a master.
Model your objects by keeping real world objects in mind.
We are currently developing automation software for machines. One of those machines has two load ports for feeding it raw material, while all others have only one. In all modules so far, we had the information of the ports (current settings, lot number currently assigned to it etc) as members in the class representing the machine.
We decided to create a new class that holds the information of the ports, and add two LoadPort members to this MachineXY class. If we had thought about it before, we would have done the same for all those single port machines...
You should look at UML, which is an entire process given to OOD.
I'd recommend getting a book (or a couple), because the theory is quite large, most people pick and choose the techniques most appropriate for the project at hand.
Start reading about design patters, from say Martin Fowler. :)
They are the most practical use of OOP.
I am guess you mean OO in the database world.
Object-oriented databases which store objects never did really catch one so you are currently looking mapping objects to relational database. ORM or Object-relational mapping is the term used to describe the software that does this mapping. Ideally this gives you the best of both worlds where developers can internact with the objects and in the database everything is stored in relational tables where standard tuning can take place.
in DBA slang: object-oriented design is nothing else but properly normalized data behind safe operation interfaces, safe meaning, look at the operations, not the data directly
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I find that whenever I begin writing an app in Java/C#, things start off good, but over time, as the app becomes more complex, it just gets more and more complicated. I've become aware of the fact that I'm not very good at design and high level architecture. All my classes become fairly strongly coupled and the design isn't "elegant" at all. I'm fairly competent at "low level" programming. That is, I can get just about anything done within a function or a class, but my high level design is weak and I'd really like to improve it. Does anyone have pointers to techniques, books, etc. that would be helpful in making me a better software engineer?
I disagree about starting with a book on design patterns or refactoring.
In my opinion, for a solid OO design, you should first be familiar with the main OO design principles, then understand how your problem can be represented in those basic principles. Then you can start discovering opportunities for applying design patterns and refactoring techniques in order to achieve those fundamental principles.
I would start with this book:
Agile Software Development, Principles, Patterns, and Practices by Robert C. Martin
In this book, Robert Martin describes the fundamental principles that make a good OO design, all of them related to encapsulation, coupling and modularity:
The Open/Closed Principle
Liskov Substitution
Dependency Inversion
Granularity
Common Closure
Reuse
No Cyclic Dependency
Stability Of Dependency
Abstraction And Stability
After all, almost every Design Pattern and Refactoring technique I have seen documented in GoF and Fowler is aimed at achieving one of several of these basic principles, depending on their relative priority for a given scenario.
Books:
Code Complete, by Steve McConnel
Design Patterns, by Gamma, et. al.
I would start by sketching my design. That sketch could be a box and arrow diagram to show relationships between classes or it could be a variation on UML (or perhaps even standard UML). But I find that sketches help me see that a design is good/bad and maybe even how to fix it.
I would also look at a book on design patterns.
Write a large project and let it spread as big as you can. Then study what you can do to improve your code.
Perhaps single large routines can be clean and understandable too, if they are well-structured.
There's no single good answer on good design. It's actually one of those valuable things a programmer can learn.
You can refactor mercilessly to improve the design of existing code.
The main idea is, at some point the code did make sense, when new features are bring into the code then probably some features or responsibilities must be moved around to another classes, that's fine. Then you stop developing new features and start refacoring your code.
I would recommend you to read:
Refactoring by Martin Fowler
use Object Oriented Design Principles (http://www.surfscranton.com/Architecture/ObjectOrientedDesignPrinciples.htm). also consider some oo design heursitics (http://www.cs.colorado.edu/~kena/classes/6448/s02/lectures/lecture27.pdf)
Try making program outlines and diagrams before you start, and have someone else review and critique it. Then as the program grows, continually update the outlines and diagrams to include the new functionality. Get it reviewed and critiqued by someone else. Eventually, assuming you are learning from the critiques, you will become better at designing programs.
Books and tutorials can only get you so far. While you do need to learn the tools and methods available, knowledge on its own won't help you here. Practice is what will make you better at design, along with having a mentor coach you from time to time to show you how you can better apply some of the knowledge you've gained from the books.
Read the books by all means, but don't feel bad if you write code that ends up having stupidities in it. Everybody does. The question is, can you refactor what you have to fix it? To be able to do that effectively and often, you need to use TDD and write lots of unit tests.
I would highly recommend you try Test Driven Development (TDD). You will find that to make your code testable, and not need to constantly perform rework of your tests, you will need to have a solid design. What you will find is that when you add \ change \ remove functionality, your better designs will require a very small set of changes to a specific set of tests. A poor design will wipe out a huge set of tests - because you have tight coupling, objects responsible for multiple concerns, etc, etc, etc ...
I have found that the better I get at TDD, the better my architecture is, and the better the end result is.
Be advised, TDD takes real mental discipline. You should not expect that you use it for 1-2 days and see immediate results. You will need to really want to do it, and really make the effort - otherwise you won't benefit and likely just end up hating it.
HTH ...
There are a couple of things that you can do
Use tools for high-level and
low level design before you
actually start programming. E.g.
Creating Class UML Diagrams will
help your mind visualize the
solution in a Diagramtic form rather
than Code form.
Familiarize yourself with Java
Design Patterns. E.g. Using
Inheritance Polymorphically to begin
with will warm you up to start using
the standard Java and J2EE design
patterns.
There are a tonne of books and websites pertaining to both the subjects I just pointed out here.
Browse through good API code. For instance Spring framework code.
Read some good books such as Design Patterns (like everyone else mentioned here) and some other books on good practices. For example in Java, Head First Design, Effective Java series, etc.
C++ - Effective C++ series
I would start with : Head first object-oriented analysis and design. and once you mastered it : Head first design patterns.
Obviously, reading some of the recommmended books will help. I think Head First Design Patterns is definitely less abstract than GoF book.
The primary question I ask is "Is this code doing something very specific that could be re-used anywhwere else?" If so, put in in a class in an assembly that allows for re-use.
If you truly are just starting then one thing I used to do was to consider each database table an 'object'. So each database table represents a class. The purists will tell you this is a disaster, but I found it a good way to get myself started thinking in object terms.
Read Head First Design Patterns.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
I recently read an interesting comment on an OOP related question in which one user objected to creating a "Manager" class:
Please remove the word manager
from your vocabulary when talking
about class names. The name of the
class should be descriptive of its'
purpose. Manager is just another word
for dumping ground. Any
functionality will fit there. The word
has been the cause of many extremely
bad designs
This comment embodies my struggle to become a good object-oriented developer. I have been doing procedural code for a long time at an organization with only procedural coders. It seems like the main strategy behind the relatively little OO code we produce is to break the problem down into classes that are easily identifiable as discrete units and then put the left over/generalized bits in a "Manager" class.
How can I break my procedural habits (like the Manager class)? Most OO articles/books, etc. use examples of problems that are inherently easy to transform into object groups (e.g., Vehicle -> Car) and thus do not provide much guidance for breaking down more complex systems.
First of all, I'd stop acting like procedural code is wrong. It's the right tool for some jobs. OO is also the right tool for some jobs. So is functional. Each paradigm is just a different point of view of computation, and exists because it's convenient for certain problems, not because it's the only right way to program. In principle, all three paradigms are mathematically equivalent, so use whichever one best maps to the problem domain. IMHO, if using a multiparadigm language it's even ok to blend paradigms within a module if different subproblems are best modeled by different worldviews.
Secondly, I'd read up on design patterns. It's hard to understand OO without some examples of the real-world problems it's good for solving. Head First Design Patterns is a good read, as it answers a lot of the "why" of OO.
Becoming good at OO takes years of practice and study of good OO code, ideally with a mentor. Remember that OO is just one means to an end. That being said, here are some general guidelines that work for me:
Favor composition over inheritance. Read and re-read the first chapter of the GoF book.
Obey the Law of Demeter ("tell, don't ask")
Try to use inheritance only to achieve polymorphism. When you extend one class from another, do so with the idea that you'll be invoking the behavior of that class through a reference to the base class. ALL the public methods of the base class should make sense for the subclass.
Don't get hung up on modeling. Build a working prototype to inform your design.
Embrace refactoring. Read the first few chapters of Fowler's book.
The single responsibility principle helps me break objects into manageable classes that make sense.
Each object should do one thing, and do it well without exposing how it works internally to other objects that need to use it.
A 'manager' class will often:
Interogate something's state
Make a decision based on that state
As an antidote or contrast to that, Object-Oriented design would encourage you to design class APIs where you "tell don't ask" the class itself to do things itself (and to encapsulate its own state): for more about "tell don't ask" see e.g. here and here (and maybe someone else has a better explanation of "tell don't ask" but these are first two articles that Google found for me).
It seems like the main strategy the little OO code we produce is to break the problem down into classes that are easily identifiable as discrete units and then put the left over/generalized bits in a "Manager" class.
That may well be true even at the best of times. Coplien talked about this towards the end of his Advanced C++: Programming Styles and Idioms book: he said that in a system, you tend to have:
Self-contained objects
And, "transactions", which act on other objects
Take, for example, an airplane (and I'm sorry for giving you another vehicular example; I'm paraphrasing him):
The 'objects' might include the ailerons, the rudder, and the thrust
The 'manager' or autpilot would implement various commands or transactions
For example, the "turn right" transaction includes:
flaps.right.up()
flaps.left.down()
rudder.right()
thrust.increase()
So I think it's true that you have transactions, which cut across or use the various relatively-passive 'objects'; in an application, for example, the "whatever" user-command will end up being implemented by (and therefore, invoking) various objects from every layer (e.g. the UI, the middle layer, and the DB layer).
So I think it's true that to a certain extent you will have 'bits left over'; it's a matter of degree though: perhaps you ought to want as much of the code as possible to be self-contained, and encapsulating, and everything ... and the bits left over, which use (or depend on) everything else, should be given/using an API which hides as much as possible and which does as much as possible, and which therefore takes as much responsibility (implementation details) as possible away from the so-called manager.
Unfortunately I've only read of this concept in that one book (Advanced C++) and can't link you to something online for a clearer explanation than this paraphrase of mine.
Reading and then practicing OO principles is what works for me. Head First Object-Oriented Analysis & Design works you through examples to make a solution that is OO and then ways to make the solution better.
You can learn good object-oriented design principles by studying design patterns. Code Complete 2 is a good book to read on the topic. Naturally, the best way to ingrain good programming principles into your mind is to practice them constantly by applying them to your own coding projects.
How can I break my procedural habits (like the Manager class)?
Make a class for what the manager is managing (for example, if you have a ConnectionManager class, make a class for a Connection). Move everything into that class.
The reason "manager" is a poor name in OOP is that one of the core ideas in OOP is that objects should manage themselves.
Don't be afraid to make small classes. Coming from a procedural background, you may think it isn't worth the effort to make a class unless it's a thousand lines of code and is some core concept in your domain. Think smaller. A ten line class is totally valid. Make little classes where you see they make sense (a Date, a MailingAddress) and then work your way up by composing classes out of those.
As you start to partition little pieces of your codebase into classes, the remaining procedural code soup will shrink. In that shrinking pool, you'll start to see other things that can be classes. Continue until the pool is empty.
How many OOP programmers does it take to change a light bulb?
None, the light bulb changes itself.
;)
You can play around with an OO language that has very bad procedural support like Smalltalk. The message sending paradigm will force you into OO thinking.
i think you should start it with a good plan.
planning using CLASS Diagrams would be a good start.
you should identify the ENTITIES needed in the applicaiton,
then define each entitie's ATTRIBUTES, and METHODS.
if there are repeated ones, you could now re-define your entities
in a way that inheritance could be done, to avoid redundancy.
:D.
I have a three step process, this is one that I have gone through successfully myself. Later I met an ex-teacher turned programmer (now very experienced) who explained to me exactly why this method worked so well, there's some psychology involved but it's essentially all about maintaining control and confidence as you learn. Here it is:
Learn what test driven development (TDD) is. You can comfortably do this with procedural code so you don't need to start working with objects yet if you don't want to. The second step depends on this.
Pick up a copy of Refactoring: Improving the Design of Existing Code by Martin Fowler. It's essentially a catalogue of little changes that you can make to existing code. You can't refactor properly without tests though. What this allows you to do is to mess with the code without worrying that everything will break. Tests and refactoring take away the paranoia and sense that you don't know what will happen, which is incredibly liberating. You left to basically play around. As you get more confident with that start exploring mocks for testing the interactions between objects.
Now comes the big that most people, mistakenly start with, it's good stuff but it should really come third. At this point you can should reading about design patterns, code smells (that's a good one to Google) and object oriented design principles. Also learn about user stories or use cases as these give you good initial candidate classes when writing new applications, which is a good solution to the "where do I start?" problem when writing apps.
And that's it! Proven goodness! Let me know how it goes.
My eureka moment for understanding object-oriented design was when I read Eric Evans' book "Domain-Driven Design: Tackling Complexity in the Heart of Software". Or the "Domain Driven Design Quickly" mini-book (which is available online as a free PDF) if you are cheap or impatient. :)
Any time you have a "Manager" class or any static singleton instances, you are probably building a procedural design.