Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm kind of a beginner to Java and OOP and I didn't quite get the whole concept of seeing a real world problem and translating it to classes and code.

For example, I was reading a book on UML and at the beginning the author takes the example of a tic tac toe game and says: "In this example, it's natural to see three classes: Board, Player and Position." Then, he creates the methods in each class and explains how they relate. What I can't understand is how he thought all this.

So, where should I start to learn how to see a real world problem and then "translate" it into code?

share|improve this question

migrated from stackoverflow.com Mar 19 '11 at 18:00

This question came from our site for professional and enthusiast programmers.

9  
If the author really wrote "it's natural to see three classes", I'd say that's a bad book to learn from. These things are "natural" only after you have really grokked them. Even then, "natural" is a poor word to describe it. –  Mauricio Scheffer Mar 18 '11 at 18:41
    
It is natural if you have experience and understand how OOP works. I believe you can get there with practise and any good book. –  Johan Sjöberg Mar 18 '11 at 18:42
2  
Natural is usually pretentious double-speak for 'my way is right' :) –  spinning_plate Mar 18 '11 at 18:54
1  
Moreover: saying something is "natural" doesn't explain anything to those that don't consider it natural (i.e the readers). Not to mention that many people consider functional programming more "natural" than OOP. –  Mauricio Scheffer Mar 18 '11 at 19:21
    
I'd say it's natural to see two classes: board and gaminig pieces. Positions are not natural classes. Players are typically outside the scope and therefore not natural either. –  user281377 Mar 19 '11 at 18:34

10 Answers 10

up vote 6 down vote accepted

When considering your problem think of the "things" that the problem involves - these are usually real objects, like cars or users. These become your classes.

Then consider actions and what the actions is performed on, so a car might StartEngine, and a user might Login. These are methods.

Finally (ish) you have information about your objects, eg a car has 4 wheels, a user has a name. These are properties.

Its a bit simplistic but its a start point.

share|improve this answer
    
+1 Things; and their actions and properties is a good, simple way to start breaking the problem down. To help wrap you mind around properties of an object, you might consider the parts and pieces that 'compose' an object (or what parts go into building it; aggregation), state(s) (ready, not ready, getting ready), quality (as a special kind of state). Other things you may take note of when thinking about objects is what excites or activates them (eg. events) –  JustinC Mar 18 '11 at 21:17
    
To augment Jon and Justin: Rather than use a 'tool' to capture all this you could just stick with Pen/paper or use a technique called CRC cards (Classes-Responsibility-Collaborator) - they are just index cards where you write the name of the 'thing' identified, the actions that need to be performed by that thing (responsibilities) and who would that 'thing' need to collaborate with to 'get it's job done'. You can play around with them on a table/white board and see how to 'structure' them based on the 'collaborator' column. This should help you 'see' where you need inheritance/composition –  PhD Mar 18 '11 at 23:44

Necessity is the mother of invention. You may need to get your hands on an actual problem to solve before you can expand your ability to split it into seperable units.

Decide on some project of moderate size, and try to program it. Focus on the "nouns" and "verbs" of the problem and try to base the code structure around them.

share|improve this answer
1  
+1 It all boils down to practice. There isn't an ideal solution for every problem that can be modeled, and not all problems can be modeled effectively using the same paradigm. –  Camilo Díaz Mar 18 '11 at 18:45

Good question.

First, you think of objects from the real world problem. In the tic-tac-toe game, Player, Position, and Board come to mind.

In an XML Parser, you'd have a Decode class. Decode is more like a process than a real world object, but it's obvious that in an XML Parser, you'd have to decode the XML.

Then, you come up with what you want the classes to do. These would be the methods.

In most real world problems, you're not going to identify all of the classes and methods right away. That's okay. You identify and code them as you think of them.

share|improve this answer
    
I think "border" may be a mistranslation of "board"? –  Null Set Mar 18 '11 at 18:46
    
@Null Set: Thanks. I've corrected my answer. –  Gilbert Le Blanc Mar 18 '11 at 18:48

It's also about evolution. Don't be afraid to take a stab at something and then tear it apart when you find it just doesn't feel right. Nobody gets it right the first time.

I remember a project when I was getting started trying to get my head around OOP. I think I had classes that represented customers, dealers, products, etc. I needed to represent these as XML at some point so I added code to each class to do that. Then I realized that 'xml-ness' had nothing to do with 'customer-ness' and pulled it out. That's called refactoring and you'll do that over and over until you find a solution that is more natural.

Read, study this site (LOTS of skill here) and write programs.

It's fun!

share|improve this answer
    
Good point--I've learned the most from projects I've put together then had to completely recode from scratch. You notice that things feel uncomfortable the first time but never really feel that fixing it would be worth while (it pretty much always is). Also, one of the things you can work towards is eliminating any redundant logic--this is a fantastic goal and will help drive your design and help you understand why OO is good. –  Bill K Mar 18 '11 at 19:01

In short, translating the real world problem to code is probably the hardest part of a programmers job. The code serves as a representation of that problem and how effective the solution is, in terms of correctness, efficiency and extensibility, is a function of how well that translation is made, i.e., how well you understand that problem.

For any real world example, there are going to be lots of a class/code representations that are going to be 'natural'. It's a process of experience and experimentation to find the one that works for a particular problem - often the right designs aren't the ones that are natural and intuitive, but the ones that can be reused and extended in a sane fashion. A Visitor pattern, for example, is not something you'd find represented in your problem, but something you would impose upon it to make your solution better.

For this particular example I think your book's example is poor. On my initial reading and still, I don't know what these map to. I think my first intuitive approach would be to represent a player, the game (containing whose move it is, the whether it's complete or not) and the board itself. You could also represent the board within the player objects by keeping track of where they placed their tokens. There are endless permutations of this,even for this simple problem. There's also no right answer without knowing how the tic-tac-toe will be used, where it's running, etc. etc. (Though there are always wrong answers :) )

Learning this isn't something we can tell you how to do here. Despite the fact that you're writing code, doing this sort of translation is a bit of art - go out, see what works, try to copy it, change it a little bit, watch it fail, learn why it failed, think of ways to fix it, ask questions and break it as many ways as possible.

share|improve this answer

You should read this book: Head First Design Patterns

It gives you briliant examples of transfoming real world objects to classes.

share|improve this answer

Right now what you pick as classes doesn't matter too much. I'd just start coding. Figuring out all your objects up-front doesn't work well, you can get an idea but the entire school of thought called "Agile" has built up around the concept that you won't get it right anyway, so don't stress it, just code.

You can take some steps to make your code better as you go:

When you notice that you are passing the same 2 or 3 pieces of data around to a few methods, look at them, they have something in common. Consider what that data "Means" and make an object to represent it and encapsulate that data.

If you notice that a method doesn't access any members in your object, it's probably not in the right place. Also if a method takes an object as a parameter and uses it a LOT, it should probably be a method of that object (and not take the parameter)

I've almost never seen an object that's too small/you can (almost) never have too many objects--so break objects into new objects a lot. I suppose if two objects live and die together and are always passed to the same third object you might consider combining them.

Don't use inheritance unless it really makes sense--consider it a last resort and always prefer having one object contain another instead.

Just iterate over these steps (and check the book "Refactoring" for more) and your code will turn out okay.

Once you get in the habit of how good OO code is written by writing it, you'll find it's easier to answer a question like the one you posed.

share|improve this answer

For school problems, the problems are usually simple as the professor usually will provide detailed requirements and they already know the solution.

For actual consulting jobs, things get hairy as the customers tend to not know how to articulate the solution (if they did they won't really need consultants). Let's presume it is a consulting job you are asking for and not a school problem.

For the most part most business problems I have experienced can be broken down into OO methodology as the main container. This is because it is easier to communicate with non technical people in those terms.

First steps are usually to get good requirements. From those you can start breaking things apart into use cases. A typical use case diagram will show interaction between a user and a system, and sometimes system to system. The interaction will show "actions" that would be performed and a direction. In simple OO concepts, you now have broken down your problem into objects that interact with each other. You have also done one of the paradigms which is encapsulation.

From there you continue to break things apart into smaller objects that talk to each other. At this point no code has been written yet. Right now you are on designing still. However as you go through it and refine things you get to start seeing how things would be assembled and you can start building in those stages. However, don't start building yet.

At this point comes experience and understanding design patterns and other modelling techniques. You want to start grouping things together or breaking things apart or moving things around until you are comfortable you are not repeating yourself too much or making things wired so it becomes like spaghetti. Don't over analyze though, just allocate maybe 2 to 4 hours, it is usually enough for most applications where a framework has been defined for you, 4-8 if you're building a framework. The reason I say this is because I am lucky enough to use IDEs that support refactoring so I can change my mind and move stuff around as needed.

Add a few tests to prove your thing works. You don't need to test everything, but try to get good enough coverage. The test cases will allow you to refactor more fearlessly because you have something to double check that whatever you did, didn't break any existing expectations.

There you go you now have translated business requirements into an object model which you have mechanically translated to code for the most part.

You can stop here if you want, or you can always go back and say, there has to be a better way of doing X and adjust accordingly. Just don't go past your limit.

Just a reminder again, OO decomposition is not applicable to all cases especially when it comes to dealing with business users. I do rule decomposition (sort of a cross between functional and declarative programming) and workflow decomposition. However, OO decomposition is the easiest to understand (not necessarily to do it).

share|improve this answer

Although I started in OOP, I often find that my thoughts on a new problem drift closer to one of two much more basic methodologies.

1) What are the data and structures that I'd need?

This is identical to the OOP "what objects do I need" but more basic, easier to understand. Say I have the requirement "Read an address book file, send an email to all the email addresses in it." I know I'll need to keep a collection of address records as I read them from the file, so I know I'll need a collection. Usually a List or Array is a good start. If I need "named access" I'll use a dictionary/map. More specific data structures fill particular roles that you'll learn as you go (queues, dequeues, stacks, sets, etc.)

I'll also need address records, so I figure out what I need to track: name, email address, phone number, etc. That's my basic objects right there.

2) What inputs and outputs am I dealing with? What methods would bridge those?

A computer is nothing but input and output. A program inputs and outputs. A method inputs and outputs. If you break your problem down step by step into what goes in and what comes out, you'll often begin to see a solution. I have a List of Addresses (input) and I need emails (output). (Okay technically emailing is probably a side-effect, for all you Functional Programming purists, but we'll say its one of many potential outputs.)

I look in my language documentation for how to email things. I write methods that use those library methods. I need a place to put those methods, so I make a new class and call it "SpamBot3000". I need a way to manage my spam bots so I make another class called "SpamBotManger" and so on. Once you've defined the base problem and started on it, the rest of the classes will usually manifest themselves as necessities.

As a final example, your Tic-Tac-Toe player. My first thought would have been, "I need a board. I can probably use an array of chars for that, holding 'x' 'o' or ' ' as needed." Then I'd put that array in a class, Board. Then I'd add simple methods like "SetSpaceToChar(char c)". Then I'd go "Right, I need a 'Player' class to actually handle whose turn it is and which letter to put. Maybe a 'Game' class to keep score." Then later on I'd think, "You know, letting people put any char into the grid is dangerous. I should switch from char to a specialized type, 'Space' that can only be x o or blank."

In that light, as tiny steps that build on each other, maybe the class structure makes a bit more sense.

share|improve this answer

Not all problems have to be solved in an OOP fashion.

Real world programs are mash up of different styles.

You will generally find that code goes through a few states:

(1) You start with a clean solution (possibly). (2) It goes live and bugs are found. (3) Bugs are fixed, code becomes more stable. (4) New features are added, the "clean-ness" starts to drop. (5) After many cycles, the initial clean structure becomes a complex mess. (6) Sometimes refactoring occurs. (7) Code is either re-written OR slowly slimed down and cleaned up.

During the clean up OOP may be used to achieve good code - reuse.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.