• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Ron McLeod
  • Paul Clapham
  • Jeanne Boyarsky
  • Liutauras Vilda
Sheriffs:
  • Rob Spoor
  • Bear Bibeault
  • Tim Cooke
Saloon Keepers:
  • Tim Moores
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Piet Souris
Bartenders:
  • Frits Walraven
  • Himai Minh

Move from procedural to OOP

 
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a project that works using procedural code. I want to convert the code into a project that uses OOP to achieve the same result.

Currently I have:

A Product class with no members:



An Inventory class with no members:


and a class with no proper name, called Test, where all the procedural code is housed that works on the Product and Inventory objects.

Is the following the correct way of thinking about moving from procedural to OOP:

Currently, I have this method in Test.java:



I would move that to Product.java, with line 13 removed. What would I return:



Would this be the correct way of calling it from Test.java:



How do I implement line 13 in an OOP manner:


How would I make it work?
 
Marshal
Posts: 72993
330
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:. . . A Product class with no members: . . . An Inventory class with no members: . . .

No, those classes both have members, viz. their fields and methods.

and a class with no proper name, called Test, where all the procedural code is housed . . . Is the following the correct way of thinking about moving from procedural to OOP: . . .

Afraid not.

Even Bertrand Meyer (in Object‑Oriented Software Construction) recognises the fact that sometimes you need a method without an object, and says that object‑oriented programming should be called class‑oriented programming, though nobody else uses that term. What you want is to open a file, read it and create a List<Product>, and none of those things requires a pre‑existing Product object. In fact, that List<Product> might contain the first ever Product object you see. Also, there is no interaction between the List, the file and the object you are calling your method on. That makes it a 1368 in the most dubious classification of methods ever seen. That means you would consider making it a static method. That also gets you out of giving Product a public no‑arguments constructor, which simply constitutes an invitation to create an object not in a consistent state.
What is fileDelimiter?
That technique of creating objects is error‑prone and needs lots of defensive programming to make it robust. Don't catch the file not found exception here and don't close the JVM with System.exit. (Actually, avoid System.exit as much as possible.) Declare that your method might throw the exception with a throws clause and let the calling method try and find the correct file. If the file is of the wrong format, you will get an input mismatch exception (=IME); you are probably right to allow that to propagate, but you might do better to catch that exception and replace it with a more familiar type of exception:-Unfortunately, IME doesn't seem to get an informative message to tell you where the error was.
I would use a Path rather than a File; see this constructor.
I see you are up to date with try‑with‑resources Remember how important the documentation comments are. If your file is the wrong format or can't be read, let the calling method find a different file. That method is akin to a factory method, so it would usually be a method of Product.
A zero‑element List is a much better thing to return than null if your file is empty.
 
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:How would I make it work?

Hmmm. Lots of questions there. I have a few of my own.

1. What is Inventory? What does it do?
2. What is Product.ID? It sounds like the way a database might distinguish between Products, but isn't strictly necessary for a Java Product class.
And IDs are usually numbers.

Personally, I'm a firm believer that all classes should be able to "create" themselves in whatever way they need to; and if that means adding a constructor or factory method that takes input from a Scanner, then it should have one, viz:
and then you can use a slightly modified version of Campbell's method, viz:

Hope it helps

Winston
 
Saloon Keeper
Posts: 23729
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Sorry, but a lengthy debate on closing Scanners has left me convinced that proper software hygiene would always close the scanner object. And here, in particular, there's no requirement to read the input source after scanning is completed.

I did a lot of meditating on what is and isn't OOP and what is and isn't procedure-oriented some time before Java was invented. I was heavily involved with C++ at the time, and C++ inherited a lot from the decidedly procedure-oriented C programming language. It is perfectly possible in C++ to write programs that are entirely procedural. Hence, I decided that Object Oriented was a passably good description for C++. You could use objects, but it was a direction (orientation) that you were not required to follow.

Java, on the other hand is Object based. There is no such thing as free-standing code in Java. Everything must be defined within a class. You can create some really horrible class definitions, like with 2000 lines of single-method code, and that is a way to code procedure-oriented style in Java, but there's still the object framework underneath. And, in truth, there's not much you can do in Java without touching at least some objects, even if only the iostreams.

Fun story: Even before C++ I was working with a Pascal compiler with a co-worker. He had a COBOL background, which means basically as procedure-oriented as you can get. Note that "procedure" can simply mean a single process, but it also is a synonym (or even a keyword) in POLs for "subroutine" or "function", and COBOL isn't real big on subroutines - usually a "PERFORM" is as far as you can get. And note also, that these words are not used in Java. Java works with methods.

So he's coding in Pascal one humongous block of code. And the compiler rejects it.

The compiler had been designed with function-oriented programming in mind - breaking the process into smaller procedures. In fact, the code generator counted on this type of design to output the first compiler-generated code I'd ever seen that made hand-written assembler look truly inefficient. The machine it targeted only allowed for about 8K of machine code per procedure, max. He was very frustrated, as you can imagine.

Which also reminds me of this one program in the same shop. It was written in COBOL. The IBM COBOL compiler of the day could deal with a maximum of 65,536 distinct code labels in a source module (GOTO and PERFORM targets). Guess what they did? Twice.

 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:Sorry, but a lengthy debate on closing Scanners has left me convinced that proper software hygiene would always close the scanner object.

Yup, in the above case I agree, because the method is reading the file to exhaustion.

However, closing a Scanner linked to System.in is usually not a good idea, because you (probably) don't want to close the underlying InputStream.
I've been out of touch with Java for a while now, so I'm not sure if there's a way of "unlinking" a Scanner without closing its stream.
Maybe you can enlighten me?

Winston
 
Rancher
Posts: 4801
50
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:



Where were you thinking of putting this code?
All the above code is using a try-with-resources call anyway, so I'm assuming I missed something...
 
Tim Holloway
Saloon Keeper
Posts: 23729
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I guess you missed the big debate. Campbell and I picked the subject apart in a recent thread, and one thing we unanimously agreed on is that Scanner is an abomination.

Beyond that, Sun deliberately and with malice aforethought assigned System.in to an auto-closeable/closeable Stream, so presumably there was a good reason for it. And certainly abandoning any object before telling it you're done with it is not good practice.

Frankly, I still consider reading only part of System.in through a Scanner as something more likely to be the exception than the rule. But if that's what was needed, I'd generally either read line-by line and run a Scanner on each line (and, alas, Scanner is not re-usable, so construct a new one for each line), OR I'd create an overlay class mapped onto the System.in stream that was mostly pass-though except that close() was a no-op and probably that had its own readline method (since System.in is a simple stream and not itself line-oriented - it can and often does read binary data). That would allow Scanner to accept a known safe data source, it could close the scan input without closing System.in and not risk losing partial lines or having other unpredictable behaviors that might go "snap" in some future Java release.
 
Marshal
Posts: 7982
560
Mac OS X VI Editor BSD Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I find this saying "Java is OOP" so use objects is a bit fuzzy. Except that everything in Java must be in a class, so you almost have no choice actually.

For me to understand object oriented programming is easier when I think along the lines of separation of concerns. When you apply that? Whenever it makes sense!

If that something you are dealing with is a printing job, you separate printing job from whatever you designing now and assign it to a responsible entity - presumably a Printer (a class; if you don't have one - you create), so you create a method i.e.: void print(Document document) in it. So you have:

That way you design your system carefully assigning responsibilities to those, for whom it makes most sense to assign them according to best of your knowledge at a given point in time. That knowledge usually comes (sometimes it still doesn't at the end of the day ) from common sense, but it is not easy.

So why RegistryOffice uses printer to print document and not directly somebody asks printer to do that for them? Well, imagine you went to an embassy, so really you don't care how they print you a document, whether they use a habitual printer or some other technology, that's their concern which you assigned to them to print you a document, now they think that really such printing is done at an actual Printer level, so they use its services.

And that way you declare lots of objects which provide you some services based on a small set of actions they can do for you.

A warn: whenever you decide that you want to cut corner and add print(Document document) method to i.e.: Employee class, form this moment your API becomes unpleasant to use, as you don't know what to expect from entities, what they actually can and cannot do for you. When you read such code, you need to read it through several times until you think you can assemble virtually what they can do, but that's something out of common sense scope anymore.
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tim Holloway wrote:I guess you missed the big debate.


I guess I did, but agree totally with your synopsis. :-)

Winston
 
Tim Holloway
Saloon Keeper
Posts: 23729
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The other thing about OOP that's very important is inheritance. Like the old classic article I read long ago when OOP was still new and radical:

Let's say you have a Galaxy (aha! that's an object!) and it's full of Empires (more objects!) and they have Spaceships (!). And, of course, every Empire has its own type of Spaceship. For example, Bird of Prey, Romulan cruiser, and, of course, Orion ships.

Now each ship has common characteristics. But shapes are different, weaponry may be different, some may have cloaking capabilities - and different energy signatures.

So you can cut down on a lot of work if you make Spaceship a base class, subclass it into different varieties such as Constitution class, and then create instances, each with their own ID (say, NCC-1701).

So we have Separation of Concerns - A Starbase class would have different properties and methods than a Planet class or a Starship class, but also shared commonality (for example, Starships have Warp Drives). making it easier to manage complex logic shared between multiple civilizations.

And you can easily adapt to changing circumstances. Say, for example, if you wanted an Orion-class starship with suicide capabilities, you could sub class Orion to change its energy signature.
 
Jay Rex
Rancher
Posts: 59
7
Java Windows
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Campbell:

What is fileDelimiter?




Products.txt


Inventory.txt


That technique of creating objects is error-prone


How would I do that in a better way?

I see you are up to date with try-with-resources


Thanks to you

Remember how important the documentation comments are.


The more I read about comments, the more I see that people advising against writing comments. It is usually advised to only write a single line comment if the method name would be too verbose to describe the intent. Are documentation comments seen in a different light?

That means you would consider making it a static method.


Where do I create the static method, inside Test.java or Product.java? Is one more correct than the other?


Winston:

What is Inventory? What does it do?


I was advised against storing quantity inside Product, which makes perfect sense, so I created an Inventory class that only stores the item code and the quantity.

What is Product.ID? It sounds like the way a database might distinguish between Products, but isn't strictly necessary for a Java Product class.


It's simply a unique product identifier.


Tim Holloway:
Thank you for your recollection. Very interesting. My coding style seems very procedure-oriented currently. I want to see how I can leverage the object based strengths of Java.


Liutauras Vilda:
Thank you for your post. That makes much sense.


Here is the outline of my console program currently:

Product.java
Inventory.java
Products.txt
Inventory.txt
Test.java: Contains all the methods required to make the program work.

The program does the following:

Products: List, Add, Edit, Delete
Inventory: List, Add, Edit, Delete
Read the Products from Products.txt and writes to a new copy of Products.txt after Add, Edit and Delete actions
Read the Inventory from Inventory.txt and writes to a new copy of Inventory.txt after Add, Edit and Delete actions

What would be a better name for Test.java?
 
Tim Holloway
Saloon Keeper
Posts: 23729
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
fileInpute should have been named fileScanner.

fileDelimiter should have been tokenDelimiter. As it is, I first expected it to be the file path separator character.

Names have meaning.
 
Liutauras Vilda
Marshal
Posts: 7982
560
Mac OS X VI Editor BSD Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:The more I read about comments, the more I see that people advising against writing comments.  Are documentation comments seen in a different light?


I don't think anyone advice not write comments, however, you need to understand when to write them and what kind. Javadocs you supposed to write for all public API methods, describing its inputs, outputs, corner cases, thrown exceptions.

Jay Rex wrote:It is usually advised to only write a single line comment if the method name would be too verbose to describe the intent.


If the method name becomes too verbose to describe what method does, that's an indication that method does too much. Always prefer clear method/variable name over the explaining comment.

Some other type comments:

BAD (nothing new said)
// initialize count to 4
int count = 4;


BETTER (even though it is nonsensical, but get an idea)
// initialize to 4, because it is my lucky number
int count = 4;
 
Tim Holloway
Saloon Keeper
Posts: 23729
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a very basic set of rules for comments:

1. Throughly javadoc all public methods and variables as well as the class. With an option to do likewise on the internal stuff. You might notice that I include javadoc comments on almost all sample code I post to the Ranch. I also use package level documentation. My best projects can be javadoc-compiled into a complete logic manual.

2. Comments work best when they tell you what the item being commented is for, why it exists and what it's supposed to accomplished. The how shouldn't need comments except at the highest level (e.g., implements the Black-Scholes Algoirithm, does a binary search). Java is a sufficiently abstract language that the detailed how should be apparent from the code.
 
Campbell Ritchie
Marshal
Posts: 72993
330
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:. . .

That technique of creating objects is error-prone

How would I do that in a better way?

If you are reading from a text file, you are stuck with that technique. You have the awkward task of ensuring that the format of the file and the way you are reading it match. You are now coupled to the format of the file, and I think that is unavoidable.
There is another way to read things: read a whole line with your Scanner and divide it into an array with String#split; you can probably use ";" as the regex. Please check, but I think the semicolon isn't a meta‑character.

I see you are up to date with try-with-resources


Thanks to you

Gee, shucks, you got me all 'barrassed!

. . . . Are documentation comments seen in a different light?

Yes. You use the javadoc tool to create an HTML document which you open with a web browser, and you use the documentation comments to guide you about how to use the code.

. . . Where do I create the static method, inside Test.java or Product.java? Is one more correct than the other? . . .


If you use a factory method to create an object of a class, it is usual to put that method in the same class. So Product in this case.

. . . What would be a better name for Test.java?

There isn't a really good name for that sort of class, but how about ProductDemo?
 
Winston Gutkowski
Bartender
Posts: 10777
71
Hibernate Eclipse IDE Ubuntu
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:

What is Inventory? What does it do?

I was advised against storing quantity inside Product, which makes perfect sense, so I created an Inventory class that only stores the item code and the quantity.

OK, so presumably you want each Inventory item "linked" to a Product - which in turn suggests that you must have a Product object before you can create Inventory for it.
So how about:
Does that make sense?

Winston
 
Sheriff
Posts: 16278
271
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:that object‑oriented programming should be called class‑oriented programming, though nobody else uses that term.


James "Cope" Coplien vociferously asserts that Java is a class-oriented, not object-oriented language. Every time he gets a chance.
 
Tim Holloway
Saloon Keeper
Posts: 23729
161
Android Eclipse IDE Tomcat Server Redhat Java Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Junilu Lacar wrote:

Campbell Ritchie wrote:that object‑oriented programming should be called class‑oriented programming, though nobody else uses that term.


James "Cope" Coplien vociferously asserts that Java is a class-oriented, not object-oriented language. Every time he gets a chance.



I think he's about 50 years too late, at this point. And we were calling it "Object Oriented" for maybe 15 years before he wrote his first book.

Admittedly, Stroustrup initially called C++ "C with classes", but if you want to pick nits, the classes are the templates. What you are actually going to be working with in most cases are instances of classes. Or, as we sometimes call them: objects.
 
Liutauras Vilda
Marshal
Posts: 7982
560
Mac OS X VI Editor BSD Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
What I've been taught, that "Object is an Instance of the Class" (which I think is correct terminology, at least makes sense to me), and at the same time I figure out, that Instance and Object are used interchangeably, which I admit might be confusing for starters: instances, objects, classes, which cause  

For starters (please correct me someone if I'm off in terminology):

Person p = new Person();

1. So Person is a class - a specification, which defines what object is capable of once instantiated.
2. Once you write "new Person()", you instantiate Person class, which in turn gives you back an object (a constructed specific object based on for example passed argument(s)).

Instantiation is really a creation - at least how I map that in my head. But what you are operate with are objects. This is I think is in sync what garbage collector says, "object becomes eligible for..." (not the instance).
 
Junilu Lacar
Sheriff
Posts: 16278
271
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Jay Rex wrote:I would move that to Product.java, with line 13 removed.


I wouldn't. A class with a name like Product strongly suggests "domain object".  I keep concerns like "loading" away from domain objects, especially when it means "load from file/database/etc." -- this is an infrastructure concern and it's best to leave these responsibilities to infrastructure-related classes like DAO implementations or service endpoint handlers. A class with a name like ProductRepository would be the better choice to house that code.
 
Junilu Lacar
Sheriff
Posts: 16278
271
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Likes 1
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I would agree with the choice to not have Product.quantity. I often find these four archetypes useful: Role, Moment-Interval, Description, and Party/Place/Thing. A Product would fall under the 4th archetype, Party/Place/Thing. The product quantity would fall under the Moment-Interval archetype since its value would be dependent on time.

I might play around with names like InventoryLevel or StockLevel. To me, Inventory is a collection of Products associated with some kind of level. It could also be associated with a place of storage like a Warehouse or even a Bin.

I wouldn't get too wild with the speculative design though. I would start with usage scenarios and build out the design as I learn about the needs through testing and experimentation.
 
Please enjoy this holographic presentation of our apocalyptic dilemma right after this tiny ad:
Thread Boost feature
https://coderanch.com/t/674455/Thread-Boost-feature
reply
    Bookmark Topic Watch Topic
  • New Topic