Java Forum / General / March 2007
Yet another OO question...
ChrisW - 26 Mar 2007 19:57 GMT This might seem like a really stupid question, but I've realised that one of the main problems I've got understanding OO (and teaching myself) is that I don't actually know what to put into different methods. I'm relatively happy doing basic procedural stuff, and I've got a ~300 line program which I'm trying to make OO, but I don't know where to start because I don't know where to split my program into different methods (if that makes sense...). I'm about a third of the way through Thinking In Java, and it's a lot better than most of the other books I've read, but until I understand *what* to actually put into a method I guess I'm not going to get very far! If anybody's got any suggestions where I can get more info, or people can explain how they got through this (surely everyone must go through this mind-set when they start OO stuff, or do some people just get it naturally?!). I can explain the program I'm trying to convert and / or post some pseudo code if that helps,
TIA, Chris
Mark Space - 26 Mar 2007 20:51 GMT > This might seem like a really stupid question, but I've realised that > one of the main problems I've got understanding OO (and teaching > myself) is that I don't actually know what to put into different > methods. I'm relatively happy doing basic procedural stuff, and I've I don't think I understand OOD completely either, but I seem to be a bit further along than you so I'll try to answer your questions.
I often tend to treat objects like data structures. By one definitions, a data structure has the data needed (for example, an array of integers to implement a stack) plus the procedures needed to operate on that data (for example, Push, Pop and isEmpty).
An object should be just the same. It encapsulates the data and the procedures (methods) to operate on that data.
Class Stack { private int [] myData = new int [20]; public void Push( int i ) {...} public int Pop() {...} public isEmpty() {...} }
And there's a simple object, baring any syntax errors I may have introduced.
However, beyond that, it depends mostly on the overall design. I'd advise you to get some books on basic design. Maybe some basic books on UML would help you next. These go from basic customer requirements to implementation, so you can get an idea how a design breaks down into methods. I haven't used Learning UML from O'Reilly, but it looks good from the comments on Amazon. McGraw-Hill also puts out a Beginner's Guide series that's pretty good.
So the most important answer I can give you is: it depends on your design. Methods that might be a good idea for a class in one design could be a really bad thing for a different design. I don't think that you can just stumble on this somehow or learn it from a book. You'll have to try to make a few basic designs, then implement them, to start to get the hang of it. Try to give yourself a few exercises doing this to start off with. Start small, like a simple pong or hang-man game!
Finally, there are a few more common object types besides "data structures." There are also "drivers." Drivers contain few or no data. They have long, involved methods that function to take "data structure" objects and DO something with them. They drive the flow of the program, much like a procedure does. Collecting related driver methods into a single object is often a good idea.
Also interfaces are popular. These are also data-less objects, but often have much shorter methods than drivers. They function primarily to give someone else (programmer, user, another API, etc.) something simple to call, while they hide some complexity and make calls on behalf of the other users.
Ok, that's all for now, good luck!
Lew - 26 Mar 2007 22:46 GMT > An object should be just the same. It encapsulates the data and the > procedures (methods) to operate on that data. [quoted text clipped - 6 lines] > public isEmpty() {...} > } Just a small aside: there is a source code convention promulgated by Sun and well established in the Java community, with one or two popular but minor variations (such as where to place the opening brace of a statement block). Among other aspects it suggests that method, instance variable and method variable names begin with a lower-case letter, with upper-case letters at the start of each compound word part ( thisIsAnExample ); class names should start with an upper-case letter and use upper-case for the first letter of each compound word part ( LikeThis ); and static final immutable variables should be spelled in all upper case, with underscores to separate compound word parts ( STATIC_FINALS_LIKE_THIS ).
The above example won't compile (even if one fills in the ellipses in the method bodies) because it lacks the 'class' keyword.
-- Lew
Mark Space - 26 Mar 2007 23:28 GMT > statement block). Among other aspects it suggests that method, instance > variable and method variable names begin with a lower-case letter, with
> The above example won't compile (even if one fills in the ellipses in > the method bodies) because it lacks the 'class' keyword. Yeah I booggered that up a bit more than I should have... thanks for the corrections.
Jason Cavett - 26 Mar 2007 22:08 GMT > This might seem like a really stupid question, but I've realised that > one of the main problems I've got understanding OO (and teaching [quoted text clipped - 14 lines] > TIA, > Chris Fortunately, an OO language was the first language I learned, so it kind of made sense right away (or quicker than average, maybe).
The description I remember reading that best clarified OO for me was the following:
A house. A house is an object. It has properties (height, width, etc.) and it contains other objects.
Those other objects are things such as: Windows. Doors. Rooms.
Windows are objects. They have properties (height, width, are they opened/closed, type) Doors are objects. Rooms are objects. They have properties (name of the room, dimensions, temperature of the room, is it carpeted, etc.) and they also contain other objects (furniture, electrical outlets, etc.)
Since a house HAS windows, doors, rooms and other objects, you can determine how many of those by counting what the house has. For example, since a house has a kitchen a dining room and a family room, you can "count" that it has three rooms.
Basically, just think of things as you would in real life. Everything breaks down into smaller components. The design comes into play when you determine WHAT an object does and how small to break down it's components.
For example, it wouldn't make sense to take that program about a house and break it down into the following: house -> rooms -> atoms -> electrons That's going too far. Stop at rooms if that suits your needs.
Also, as I stated a minute ago, you have to know WHAT an object does. For example, the basement (a Room in the House) may have Heater. A Heater is object that heats up the house. (What does it do? It warms the house.)
Now, from a strict design standpoint, it may be a good idea to separate how the heater heats up the house and how the heater appears to the house (model/view/controller type stuff) but that's beyond the scope of a basic understanding of OO.
Now...here's your breakdown of your house.
House Rooms Windows Doors
Something like this can easily lead to a common interface, but I don't know how much you know/don't know and how much of this makes sense so far. Let me know if this helps (and any other people out there - feel free to correct me...I realize I have *a lot* to learn still).
Hope that at least clarifies some things for you, Chris.
P.S. Yeah, if you want to pseudocode out what your program does or something along those lines, it'd be fun to take a look at it and see if there's a logical OO breakdown. One thing to remember - sometimes certain tasks just aren't OO.
Mark Space - 26 Mar 2007 23:41 GMT > The description I remember reading that best clarified OO for me was > the following: > > A house. > A house is an object. It has properties (height, width, etc.) and it > contains other objects. While your example was pretty good, the only thing I'd criticize is that objects are often not physical objects in the real world. One might have a design with a house as a object if one was, perhaps, writing software for an architect or a home loan mortgage company. But more often than not objects will not be physical objects but things like a checking account or a network connection.
Those things (especially the latter) are likely to appear in an appropriate design, and contain behaviors that a programmer would likely want to encapsulate. And in fact the basic Java API does contain a network connection object, which encapsulates a lot of behavior for you.
So I guess maybe that's another good word to describe objects: encapsulation. Related concepts (all the variables needed to maintain a network connection), plus behavior (methods) and much if it hidden (encapsulated) so dealing with the object is relatively easy.
It's a basic divide and conquer strategy.
Andreas Leitgeb - 27 Mar 2007 10:01 GMT > Now...here's your breakdown of your house. Hey, I just built one. I don't want it broken down that soon...
*scnr* :-)
ChrisW - 27 Mar 2007 12:16 GMT Thanks for the replies... one of the problems is that I don't have a seasoned developer to help me! I'll lay out some pseudocode, and if anyone can tell me if it's logical to split it into different OO bits I'd be grateful :)
I'm using the JEcelApi package (which I think i probably got to work more by luck than judgement!) to read in a sheet in an Excel file, the sheet has a list of venues as the rows, and facilities as the columns - if a venue has a particular facility then a "y" is in the cell, otherwise a "n" is. However, some facilities are only available to over 18s, so the "y" is preceded by an 18 (to produce "18y" - as just a string). My program can go through and pick out all the facilites at all the venues for which you need to be 18:
class MyProg { public static void main(String args[]) throws IOException, jxl.read.biff.BiffException {
String excelSheetName = "facilites"; //Supplied by the user Open Excel file if the current sheet name (which can be read by JExcelApi) is the same as the user supplied excelSheetName, then check this sheet{
read through all the rows using an if statement{
int ageRestrictedCount = 0;
String ageRestricted [] = new String[20]; //20 facilites
read through all the columns using an if statement{
if (stringCurrentCell.startsWith("18") increase ageRestrictedCount errMsg = "Age restricted function " + sCurrentFunction ;
ageRestricted[current ageRestrictedCount] = errMsg; }
if (currentVolErrorCount != 0){
for (int k = 0; k<number of functions; k++){
if (ageRestricted[k]!=null){ writeFormatted.println(ageRestricted[k]); }
}
}
} }
I really hope that this makes sense to people. What I'm basically doing is going through the venues, and finding out which facilities they have and which they are only making available to people over 18. I'm storing that information in an array of strings, so that by the time I get to the end of the current row, I can print out which facilities for this venue are only used by over 18s.
Thanks, Chris
AA - 27 Mar 2007 16:55 GMT Hi Chris,
I fully understand where you are coming from. I did a software engineering degree some years back when OO was just becoming the norm in such courses and I thought I understood OO after the first semester, but then I realised that I hadn't really understood it until half way through the second year when the penny really dropped, and I still find that I am appreciating additional nuances even after all of these years. Different people pick it up at different rates, and it is really just a matter of working through it. Though studies suggest that if you have a procedural background you will have a harder time doing so, and some people no matter how many years coding "OO" still never get it, and possibly never will. Most of what others on this thread has said is correct, but it is still difficult to take that and conceptually apply it to your own individual problem. So lets look at yours, bearing in mind that there are hundreds of ways of addressing the same thing.
First some definitions.
Definition of an object:
Contains state, behaviour and identity.
So an objects state is stored in its class variables. Hiding this state behind accessor methods is called encapsulation. The behaviour that the object provides is in how it manages its state, as well as what services it provides to its clients through its methods. If the behaviour of the object is not multi-faceted, then the class is cohesive. Identity is what makes it unique from other objects derived from the same or other classes.
Definition of a class:
Think of it as the blueprint (ignoring static state and behaviour for this exercise) of the object. So the class is the skeleton or outline of what you want, it is the compiled source code. The object is the instantiation, the hydrated, living implementation of the blueprint. So an architect may design a house (the class), and a builder(the jvm) will implement the design and build any number of individual houses (objects) of the same plan.
Definition of an interface:
This is the beginning of conceptualising OO, and as such don't be too concerned if you think you understand what is written but struggle to understand how to apply it. Think of a interface as a contract. It has no behaviour, state or identity. However it does have methods (again ignoring static imports and static final constants). Any class that implements an interface is saying that it will offer those methods of the interface and will take on the responsibility of providing the behaviour of these methods. Because an interface is simply a contract with no behaviour or state, you can never instantiate an interface like you can an object from a class. Accessing objects through their interface contracts rather than directly eg List list = new ArrayList() vs ArrayList list = new ArrayList is preferable and contributes to loosely coupled design.
Definition of inheritance:
This is where things start to really twist your mind. There are loads of examples and analogies and I don't know that I will make things any clearer. However, a simplified summary. When a class (child class) extends another class (parent class), we are saying that the child class belongs to the same family as the parent, but provides some additional or modified behaviour, above and beyond its parent. Classic examples you see all the time in books and online: poodle (child) is a type of dog (parent), dog (child) is a type of mammal (parent), mammal (child) is a type of animal (parent). Leave abstract and concrete classes for another day.
Some basic design heuristics: encapsulation, strong coherence, and loose coupling. Stick to these as much as possible.
However putting all of that into a real world implementation is easier said than done, even for someone who does it a lot, because the more you learn, the more you need to consider and there often is no "correct" way, though some design choices are better than others, which is where you start venturing into the world of patterns, which help you communicate design concepts and use design choices that others have found useful. Plus there are always critics who believe that their way is the only way... Which then spills over into development processes, unit tests, test driven development, etc.
Back to your example. First thing, all of your code is in the main().
First step, create a method in your class, paste all the code into that method, do a MyProg myProg = new MyProg(); from the main, then call your new method myProg.newMethod(); Congratulations, you now have an object. Now test that it still works.
Then create a new interface: public interface Facility {} Add methods: public int getAgeRestriction(); and public void setAgeRestriction(); as well as a method: public String getFacilityName();
Create a different class for each facility that implements the Facility interface. eg public class XxxxxFacility implements Facility {} and provide each class a private final static String name constant, specific to the facility type.
Next, create a new class: public class Venue{} In this new class have a private List facilities = new ArrayList(); As well as a method to add a facility to the venue and another method to print out the facilities that this menu contains based on the minimum age passed in as a parameter.
In your MyProg class, create a List venues = new ArrayList();
Then for each row, add a new venue to your venues list. Then for each column in the row, add the appropriate facility class (reflection and / or a Factory would make this easier, but leave that as a later learning) to the venue, setting the facilities age restriction.
Finally in the MyProg class, you can iterate through the venues and have the venues print out the facilities that it contains that match the age criteria.
As an additional exercise, you could have the excel sheet name passed in as a command line parameter, rather than as a hard coded string. Basic rule, use parameters as much as possible.
Now there are lots of things to say why the approach just taken is not that good. For one thing, why not just do an array of an array? why over-engineer things? why did you do this and not that? Well, what you have done using this approach is taken the first steps to using an OO design using interfaces and classes. So it acted as a good example to learn from. Secondly, you now have the beginnings of data objects that could be used in other ways, or passed to other applications, not just to print out the contents of a spreadsheet. It is also easily extensible. What if a new attribute was added for disabled access? This just becomes another attribute of the facility or perhaps the venue. As would contact details, booking details, etc. In fact, each facility could potentially have its own calendar object. Then you could check which ones were available for a given time period that met your min age restriction, as per the command line parameters passed in on running the application, and the spreadsheet may in future have different facilities with min ages ranging from 6 to 21 or any other range. Treating it as a value rather than as a flag will allow for future changes to the data without breaking your code.
I don't expect you to suddenly see the light from this one little example, but I hope it helps clarify or shed some light on some aspects for you. You have also just gone from 0 objects (excluding Strings) and 1 class to 22 classes (20 of which are different facilities) and 1 interface. The number of objects you will have (excluding ArrayLists) are 20 facilities * number of venues plus one excel parser object that you created from your main method (ignoring your JExcelApi object).
All the best on your journey towards OO enlightenment.
AA
> Thanks for the replies... one of the problems is that I don't have a > seasoned developer to help me! I'll lay out some pseudocode, and if [quoted text clipped - 62 lines] > Thanks, > Chris ChrisW - 28 Mar 2007 16:43 GMT I really appreciate the replies. It's reassuring to know that computer scientists had problems when they were starting out! My background is environmental chemistry so maybe I should expect it to take quite a long time to sink in! In theory, the first language I learnt was OO (I did a module called "Foundations of Object orientated programming"), but it was taught so badly I think it's taking me longer to unlearn what I learnt in that module last year than it would to have taught myself from scratch (although I'm coming to the conclusion that maybe I'm one of those people who will never get OO stuff!) The definitions people have provided have helped some of the theoretical aspects. I'm still having problems actually doing it tho. I've now got this code:
import java.io.*; import java.util.Date; import jxl.*; import java.util.Calendar;
class MyProgMethods throws IOException, jxl.read.biff.BiffException {
/*Everything that I had in my static main void class previously*/
}
public class MyProg {
public static void main(String args[]) {
MyProgMethods myProgMethods = new MyProgMethods();
} }
This gives 10 errors Compile-Time errors (mostly illegal start of type errors) - Is there something quite fundamental I don't understand? Am I putting my classes in the right place? I also think I need to re- read some OO chapters in books - I'm still not happy with things like the 'this' keyword, but I presume they're just theoretical things that I just need to read and re-read until I understand them.
Thanks again for all the replies, Chris
Oliver Wong - 28 Mar 2007 16:57 GMT > import java.io.*; > import java.util.Date; [quoted text clipped - 19 lines] > This gives 10 errors Compile-Time errors (mostly illegal start of type > errors) - Is there something quite fundamental I don't understand? "main" is not a class, but a method. Statements can appear directly within in methods, but they cannot appear directly within a class. A class can contain methods, and these methods can contain statements.
So this code is illegal:
public class MyClass throws IOException { System.out.println("Hello world!"); }
but this code is legal:
public class MyClass { public void myMethod() throws IOException { System.out.println("Hello world!"); } }
- Oliver
Lew - 28 Mar 2007 23:56 GMT "ChrisW" <c.c.wood@gmail.com> wrote ...
>> import java.io.*; >> import java.util.Date; [quoted text clipped - 19 lines] >> This gives 10 errors Compile-Time errors (mostly illegal start of type >> errors) - Is there something quite fundamental I don't understand?
> "main" is not a class, but a method. Statements can appear directly > within in methods, but they cannot appear directly within a class. A class > can contain methods, and these methods can contain statements. To add to Oliver's fine advice, classes do not throw exceptions, only methods do. This is similar to his point that statements go not within classes directly, but within methods.
> So this code is illegal: > [quoted text clipped - 9 lines] > } > } -- Lew
AA - 29 Mar 2007 14:47 GMT Chris, keep persevering and don't get too disheartened with your progress - (you will eventually get the epiphany), or sidetracked with the debates you have triggered on correct 'OO' or DB normalisation - though there is some rich material there to sinks ones teeth into if you have a mind - lol. Pity we can't be less belligerent in correcting each other though. What has emerged over the last 10 years for the success of a software project is for all members, including (if not especially) software programmers to have good communication and interaction skills, as well as to be team players, especially as projects increase in size and cross time zones and cultures. Though from the tone of many newsgroup "preachers", you wouldn't get that impression... Anyway, off my own personal soapbox.
To do step one of my previous instructions, you needed to do something similar to the following:
import java.io.*; import java.util.Date; import jxl.*; import java.util.Calendar;
public class MyProg {
public void myProgMethod() throws IOException, jxl.read.biff.BiffException {
/*Everything that I had in my static main void method previously*/
}
public static void main(String[] args) {
MyProg myProg = new MyProg(); try { myProg.myProgMethod(); } catch {Exception ex) { System.out.println(ex.getMessage()); }
} }
A "static void main(String[] args) {}" method is an entry point into the application. It has to reside in a class, though a class can only have one main() method. However, an application can have a main() method in every class if you want it to. When you call the application from the command line: java class, the java application launcher will expect a main() method in the class that you have nominated in the command line. This is sometimes useful for primitive testing, especially as a beginner, to test the specific class. You probably have enough to get your head around at the moment, so don't worry about using testing frameworks just yet (yes I know, more experienced readers will be saying heresy) like JUnit or TestNG. First get some comfort just being able to instantiate an object using the "new" keyword.
Also, it is good practice (though others will have different opinions) to explicitly state which classes you are importing rather than doing the wild card package eg import java.util.Calendar; is better than java.util.*;
Which brings up another topic. Take with a grain of salt anything that is stated as being best practice in the software industry. Having personally come from a medical background, and probably in your area with the chemical sciences as well, best practice is something that has been subject to blind trials, statistically based, is repeatable, and subject to peer review. Due to the nature of software - cost, creativity, variability of people, etc, you simply cannot subject a process to the same rigour as is possible in engineering or other sciences. Which 1. calls into question the appropriateness of the term Computer Engineering and Computer Science when referring to software development, and 2. often best practice in software development is merely hyperbole for the latest fashion fad. Oops, getting back up on my soap box again, so I will immediately yield and dismount.
Back to the task at hand. Remember that a class defines an object, and in Java, almost nothing other than import statements occurs outside of a class. An object is not instantiated or created until you call it with the "new" operator. So to create an object, we need to do an Object object = new Object(), which also calls that objects constructor on creation. You have now created an object with a reference to it held in the variable named object.
When using the "this" keyword, you are referring to methods or class variables relating to the object that would be created from the class that you are currently in. Very occasionally the "this" keyword is required such as when a class variable has the same name as a method parameter that you need to use, however in most cases it is not strictly needed, but usually it is used as syntactic sugar to aid comprehension and remove ambiguity. However, until you begin to conceptualise objects in "3D" as opposed to viewing classes in "2D", this will be a difficult concept to grasp. In fact, I believe that this ability, when looking at a class, to conceptualise/visualise multiple individual concurrently existing objects derived from that class is the first step towards "getting" OO. While I understood the theory the first day it was explained to me, it was like a revelation some time later when I actually found myself thinking this way, rather than intellectualising about cats and dogs being types of animals, or windows and doors being objects within a house object.
So in the above example, the java application launcher when passed the class name MyProg, looks for and finds the main() method, which it then executes. We have not yet created an object. Instead, we are simply running a special type of method (due to the static keyword) that is contained in the class but this method has no concept of state, as it is not part of any objects created from this class. In executing this main () method, you create an object from the class within which you are running with the MyProg myProg = new MyProg(); call. This leaves you with a variable myProg that contains a reference to your newly created object. Then you call a method on that newly created object with the myProg.myProgMethod(); call, within which you execute what you were attempting to do in the main() method previously. So are you confused yet?
This may be obvious, but I will say it anyway. The main() method only exists if you specifically add a main() method to the class. Java will not be able to start an application if you pass it the name of a class in the command line that does not have a main() method that you have explicitly added.
All the best with it,
AA
Oliver Wong - 27 Mar 2007 17:01 GMT > Thanks for the replies... one of the problems is that I don't have a > seasoned developer to help me! I'll lay out some pseudocode, and if [quoted text clipped - 9 lines] > a string). My program can go through and pick out all the facilites > at all the venues for which you need to be 18: [Pseudo code snipped. It does what you'd expect: Scans through a 2D array, and uses String.startsWith("18").]
> I really hope that this makes sense to people. What I'm basically > doing is going through the venues, and finding out which facilities > they have and which they are only making available to people over 18. > I'm storing that information in an array of strings, so that by the > time I get to the end of the current row, I can print out which > facilities for this venue are only used by over 18s. I think this solution is more naturally expressed in procedural terms than OO terms.
- Oliver
Mark Space - 28 Mar 2007 02:17 GMT > Thanks for the replies... one of the problems is that I don't have a > seasoned developer to help me! I'll lay out some pseudocode, and if > anyone can tell me if it's logical to split it into different OO bits > I'd be grateful :)
> class MyProg { <snippage>
I think I agree with Oliver. The problem has been decomposed enough that additional objects don't seem to be very useful. Nevertheless, I'll make a few comments.
First, rather than one big long main method, it might be nice if you broke the design up a little, perhaps into a simple input-processing-output model, using methods instead of functions.
(Let's see if I can do this without invoking Lew to comment on my style or syntax :))
class MyProg {
private void readFile() {...} private void processData() {...} private void printTable() {...} }
You can then have the main method call each of these as appropriate. There might be even more ways to break each method up into a few smaller methods each.
Second, it might be nice if you actually added some instance variables, and designed MyProg to be instatiated. Let's rename it ExcelTableProcessor and go from there:
class ExcelTableProcessor {
String fileName; // etc.
public ExcelTableProcessor( String file_name ) { this.fileName = file_name; }
public doIt { readFile(); processData(); printTable(); }
public static void main ( String args[] ) { ExcelTableProcessor x = new ExcelTableProcessor(args[0]); x.doIt() } private void readFile() {...} private void processData() {...} private void printTable() {...} }
This to me shows a bit more structure than one 300 line blob in a single method.
Lastly, give some thought to testing. Maybe look at JUnit, or design you own test. Just thinking about it, testing and reading from a file might be hard, so maybe this needs to be refactored to take an input stream and an output stream, and that'll help testing a bit.
Oh, and Java contains some tags to help with documentation, check into that too.
Overall, this is not really OO though, just basic design.
Just my 2 nickels.
Luc The Perverse - 26 Mar 2007 22:17 GMT > This might seem like a really stupid question, but I've realised that > one of the main problems I've got understanding OO (and teaching [quoted text clipped - 11 lines] > I can explain the program I'm trying to convert and / or post some > pseudo code if that helps, A method should do 1 thing and should be as short as possible. In general, if there is any part of a method you are about to repeat that is more than 1-2 lines, a little red flag should go up - maybe it should be its own method.
An example of a very bad function (it was not Java): I saw a script generated function which was nothing but a giant case statement invoked by a timer and incremented every time. This was to space out events evenly without using a thread. The irony is that the function itself was generated by an iterative function that could have been been used as the thread function directly (with a few minor modifications!)
It's kinda like normalizing an SQL database - if you do it to a level of absurdity then it becomes impractical.
You never want to make class cumbersome to use from the outside.
Hypothetical: Let's say you had an unusual data structure which was optimized to store and read in large chunks, but not alternate between the two [well].
You may be tempted to make two public functions
void beginReadMode() void beginWriteMode()
and then mandate that the user call this before writing or requesting data
oddDataStructure.beginReadMode(); oddDataStructure.read(...)
But this would be cumbersome for the user of the class (even if that user is you - and it would be so easy to put beginReadMode(); as the first line of your read function)
I'd say, a good rule of thumb is that every function should be able to be described in one simple sentence. (Implementation or algorithm can be more complex but explaining what the function does or returns is simple)
Eg: add(Object o) //This function adds a node into the tree. double sqrt(double n) //This function returns the square root void beginTest() //This function begins the student test
Bad: connectAndRunTest(CommObject com) //This function starts the data logger, begins collecting data, turns on the water pumps and then monitors them for correct volume over a 5 minute interval.
connectAndRunTest can still be a method! But connecting to the data logger should be a method call, collecting data will presumably be handled by another thread, turning on water pumps should be an outside call etc.
It's easy to give advice, and preach ideals on OOP. Honestly, the best way to learn is to make some honest mistakes and have a seasoned software engineer give you good feedback on a specific problem at hand.
-- LTP
:) Lew - 27 Mar 2007 00:38 GMT > It's kinda like normalizing an SQL database - if you do it to a level of > absurdity then it becomes impractical. Are you suggesting that Boyce-Codd, 4th and 5th normal forms (BCNF, 4NF and 5NF) are at "a level of absurdity"? I assume that you disagree that at least 3rd normal form (3NF) is /de rigueur/ for relational database design.
It is often feasible to implement a good database only normalizing to 3NF, but the further forms exist to prevent data anomalies, which is a sound reason. They are not arbitrary idioms but objective assessments of database structure.
I admit I constantly have to remind myself "what are those forms again?", but obscurity implies neither absurdity nor impracticality.
-- Lew
Luc The Perverse - 27 Mar 2007 05:07 GMT >> It's kinda like normalizing an SQL database - if you do it to a level of >> absurdity then it becomes impractical. [quoted text clipped - 3 lines] > least 3rd normal form (3NF) is /de rigueur/ for relational database > design. I'd never even heard of them. I am a n00b to SQL. It was supposed to be a simile
> It is often feasible to implement a good database only normalizing to 3NF, > but the further forms exist to prevent data anomalies, which is a sound > reason. They are not arbitrary idioms but objective assessments of > database structure. Maybe I should read a book
> I admit I constantly have to remind myself "what are those forms again?", > but obscurity implies neither absurdity nor impracticality. When the tables are difficult to understand and queries run slower all in the name of "mad gay" normalization - then it is silly. If you want to argue over semantics, that is silly too
-- LTP
:) Lew - 27 Mar 2007 01:06 GMT > It's kinda like normalizing an SQL database - if you do it to a level of > absurdity then it becomes impractical. Are you suggesting that Boyce-Codd, 4th and 5th normal forms (BCNF, 4NF and 5NF) are at "a level of absurdity"? I assume that you agree that at least 3rd normal form (3NF) is /de rigueur/ for relational database design.
It is often feasible to implement a good database only normalizing to 3NF, but the further forms exist to prevent data anomalies, which is a sound reason. They are not fuzzy concepts like "encapsulation" but objective assessments of database structure.
I admit I constantly have to remind myself "what are those forms again?", but obscurity implies neither absurdity nor impracticality.
-- Lew
Chris Uppal - 27 Mar 2007 07:09 GMT > Are you suggesting that Boyce-Codd, 4th and 5th normal forms (BCNF, 4NF > and 5NF) are at "a level of absurdity"? I assume that you agree that at > least 3rd normal form (3NF) is /de rigueur/ for relational database > design. Maybe not (although I'll note that anything which claims to be inherently good, all things being equal, /and/ which comes in numbered variants, obviously has some serious problems). But the parallel is not misleading.
Talk about good OO, and about good programming in general, and you are likely to get hit with half a hundred precepts which you "should" follow -- and the idea that you are writing good code, and that /as a result/ the code displays <such and such> characteristics is apt to get lost in the wash. No longer are short methods (etc) the result of a design which has been carefully micro-factored for readability, but they /define/ what it is to be "good".
Something similar can happen with DB normalisation (especially if there is someone around who can remember how the various normal forms are defined). Instead of being /symptomatic/ of a well designed data model, they come to be seen as definining a good data model.
Don't confuse the tools with the end results, don't confuse tactics with goals.
-- chris
Lee Fesperman - 29 Mar 2007 10:02 GMT On Mar 26, 10:09 pm, "Chris Uppal" <chris.up...@metagnostic.REMOVE- THIS.org> wrote:
> > Are you suggesting that Boyce-Codd, 4th and 5th normal forms (BCNF, 4NF > > and 5NF) are at "a level of absurdity"? I assume that you agree that at [quoted text clipped - 4 lines] > all things being equal, /and/ which comes in numbered variants, obviously has > some serious problems). But the parallel is not misleading. Cute, but you don't seem to know what you are talking about.
> Talk about good OO, and about good programming in general, and you are likely > to get hit with half a hundred precepts which you "should" follow -- and the > idea that you are writing good code, and that /as a result/ the code displays > <such and such> characteristics is apt to get lost in the wash. No longer are > short methods (etc) the result of a design which has been carefully > micro-factored for readability, but they /define/ what it is to be "good". Apples and oranges. The Relational Model has a solid mathematical foundation, and Normalization is built on RM. Normalization has stood the test of time. OO has no formal basis, and its design techniques are ad-hoc (best practices.)
> Something similar can happen with DB normalisation (especially if there is > someone around who can remember how the various normal forms are defined). > Instead of being /symptomatic/ of a well designed data model, they come to be > seen as definining a good data model. Normalization is a strategy for designing databases whose goals include: accurate representation of the entities involved, robustness, redundancy elimination, easing future changes, ... Do you see a problem with achieving these goals?
> Don't confuse the tools with the end results, don't confuse tactics with goals. You seem to see proper database design as a trap and prefer a seat-of- the-pants approach. That may be true for OO designs but not Normalization.
-- Lee Fesperman, FFE Software, Inc. (http://www.firstsql.com) ============================================================== * The Ultimate DBMS is here! * FirstSQL/J Object/Relational DBMS (http://www.firstsql.com)
Adam Maass - 27 Mar 2007 08:08 GMT "ChrisW" <c.c.wood@gmail.com> wrote :
> This might seem like a really stupid question, but I've realised that > one of the main problems I've got understanding OO (and teaching [quoted text clipped - 14 lines] > TIA, > Chris Umm... some general pointers:
1) First examine your data items, and do something akin to a database normalization on them. Each entity becomes a class; the relations between entities become either references to instances or collections of instances. (Realize also that m:n relationships are possible.)
2) Start writing methods. Methods belong to the class that contain the majority of the data necessary to complete the computation.
3) Tell, don't ask. Tell an object to complete some computation and return the result. Don't ask an object for its data and complete the computation outside of that object.
4) Talk only to yourself and your neighbors. That is, the only values that should be (directly) used in any method are the instance (and static) members of the class you're operating in, and the parameters to the method. In particular, do not call methods on the return values of methods you call in your method.
5) Keep your methods short and to the point.
6) Beware of adding too many methods to a class; a class that has lots of methods for different purposes has lost cohesion and is begging for a refactor. Try to keep all of the members of a class focused on a single purpose.
I hope this is helpful!
pkriens - 28 Mar 2007 07:25 GMT It is a long time ago I had this question ...
I am a bit surprised because usually the problem is choosing the - objects- (or classes), and I still think these should come first.
Your objects are the things that play an active role in your problem statement. The confusing part of many examples is, is that people doe not specify a problem. Without a problem you can not say if something is an object, nor what kind of object. If you write a mortgage program you might start out with a House object. However, it is unlikely you need the width and height for this object because it has no role in your problem domain. If you analyse further, you are likely to find out that you get to a more abstract class that plays the role of thing that is borrowed against. Its estimated value, ownership, etc are the important qualities. However, if you model a house in a 3D program it is likely you need much more details of its geometry and it is likely that you do not care at all about its other house qualities. So most important: first define your problem, then look for the actors.
Finding the objects is like writing a play. Who are the actors, how do they interact. Objects allow you to minimize the complexity of a program by simplifying the interaction between those objects. When you design, I always like to push off the complexity. Lets say I design method x on class X and need to interact with an object Y and Z. I try to make x do as little as possible and forward any complexity that requires knowledge about Y and Z to those classes. In my experience, you then suddenly find out that you designed the system but are a bit suspicious where the complexity went.
A crucial aspect in this is polymorphism. You do not always need knowledge of a concrete class, an abstract trait of the class is enough to be able to use it. Lets say you have a Printer interface (or base class) and many subclasses. The key methods to render are required to print are defined. However, on top of those primitive methods you could add formatting, pagination, adding a first page, etc. This is one of the key OO advantages, trying to do this in C, you must use switch statements in many places. What you therefore often see in C is that people create data structures with a pointer to a function table: effectively creating an OO system. OO Languages like Java have special constructs to make this very easy to do. It allows you to add more concrete types later (like for example new printer drivers).
So it all boils down to find a description of your program that minimizes the interaction between the actors. The interactions are your methods and the actors are your objects. However, keep thinking. Minimizing complexity, reducing coupling, and increasing cohesion are the most important things you want to achieve. Well, and it should of course work ... And do not forget, an object is always related to a perspective which should be your problem domain.
Hope this helps, kind regards,
Peter Kriens
> This might seem like a really stupid question, but I've realised that > one of the main problems I've got understanding OO (and teaching [quoted text clipped - 14 lines] > TIA, > Chris Chris Uppal - 28 Mar 2007 08:58 GMT > Your objects are the things that play an active role in your problem > statement. The confusing part of many examples is, is that people doe [quoted text clipped - 12 lines] > Finding the objects is like writing a play. Who are the actors, how do > they interact. Good post. I hope it helps the OP get a clearer perspective on OO.
The way I like to think of it is that an object is a "thing" with a job to do.
The job is its role. Because other parts of the system require it to work (to do its job properly) it has responsibilities. In order to satisfy those responsibilities it needs abilities. Those abilities are implemented as methods (and if it needs a memory then it'll have instance fields too). Complex systems have a fractal nature where an Object with a Job will make use of the services provided by other Objects with other Jobs in order to get it's own job done.
Working out what jobs need to be done, and the interactions between the objects that perform those jobs, is the distinguishing feature of OO design. If you need to write a logfile then there will probably be a Logger somewhere. If you need to write several logfiles then there may well be several Loggers (maybe all of the same class). If you need to buffer data to stop a fast source swamping a slow consumer, then there's a Job To Be Done there too -- you'll have a Buffer object of some sort.
-- chris
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|