• Post Reply Bookmark Topic Watch Topic
  • New Topic

creating new classes as subclasses  RSS feed

 
Ranch Hand
Posts: 86
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello;

I am just Learning Java as well as going back to University for Computer science.  I am working on a personal project.  In my project I want to implement a class that holds a "note" the note will be an object containing variables representing a title the text of the note the date it was created and a status (deleted, archived or active).  I want it to be subclass of "notes" where the notes class will contain three "CopyOnWriteArrayList<note>" lists (active, archived and deleted). I am having issues picturing how to implement the code for these.  I am having issues picturing how this should work.  I am thinking in the initialization portion of my main program I should create a new "notes" object. This is what I have so far. 

Notes.java


note.java



am I doing this right?  Can anyone please help me visualize how I want to accomplish my goals?  I want to add a built in database that will store the application data including the notes.  Any guidance would be appreciated!!

 
author & internet detective
Marshal
Posts: 37518
554
Eclipse IDE Java VI Editor
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dwane,
That's a good start. You have the conventions backwards though. Class names (like  Note) should begin with an uppercase letter. And variables (like title) should begin with a lowercase letter.

For what's next, think about common operations. For example, what two things do you need to do in  order to archive a note.
 
Dwayne Barsotta
Ranch Hand
Posts: 86
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank You;

I am actually glad I did it right (except for the conventions).  I understood that in order to delete a note, I need to make a copy of the note object in the deleted notes list and then remove the original note from the active list.  I am not sure why but I had a feeling I was not using the Class/subclass properly.   This leaves me with another issue question.

How can I access the "notes" class with out going through a note?  In the below test file I created two note objects.  The "notes" object was created when I created the first note.  In "notes" I have methods that return the list of all the active, archived or deleted lists.  In the test file I created a loop that:

1.  Gets the active notes list 
2.  Loops through each element and prints the different parts of each mote object.

While my code works I don't like how I did it, I feel like it is not "good coding".  Since I couldn't figure out how to reference the "notes class directly I accessed the method to get the active notes list through one of the note subclass objects.  How can I access the three methods to get the lists from the notes class with out going through a note subclass object?

My new "Notes.java" file reads:


My new "note.java" file reads:



And my "test.java" file reads:



Notice on the test.java file, line 28 I used "for(Note note:note1.getActive()" to get all the active notes stored in the list.  There has to be a way I can reference these lists without going through the subclass objects.
 
Sheriff
Posts: 11496
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
To me, your design has one glaring Red Flag that stands out, waving wildly like it's in a hurricane. That is exposing an implementation-focused class like CopyOnWriteArrayList in your API, especially as the return type for methods with names like getActive(), getArchived(), and getDeleted(). I would have expected those methods to be declared to return a List instead.

Another red flag for me is your choice to make Note be a subclass of Notes.  A subclass is a specialization of its superclass. I don't see how a Note can conceptually be a specialization of Notes. Is Water a specialization of Bucket? Is Candy a specialization of Bag? Is Page a specialization of Book? Is Airplane a specialization of Hangar? Maybe I'm missing something here but what is the idea you're going for with Note as a specialization of Notes?  If your only reason is so that you can conveniently access these methods that return a CopyOnWriteArrayList from Note, then you're abusing the inheritance mechanism.
 
Junilu Lacar
Sheriff
Posts: 11496
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's an example of how I would have expected to see those methods I mentioned:

Look up new JavaDoc tags in Java 8: @implNote to see more examples.

I still have an issue with the impropriety of making Note a subclass of Notes.
 
Junilu Lacar
Sheriff
Posts: 11496
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Just tonight, I wrote about a vicious cycle that can be created by allowing poor design decisions to beget more poor design decisions. Here's another chunk of code that gives off a bad smell:

Why would a Note have to explicitly go to its superclass to find out what its status is? One would expect a Note to know and manage the state of its own status based on the things that it has done as a result of its methods being invoked. This code reflects a flawed conceptualization that is a direct result of a prior poor decision to make Note a subclass of Notes.

I would try to not just critique your design but also give suggestions for alternatives but I don't know enough about your problem's context to make those kinds of suggestions. If you could share more details about what you're trying to achieve, maybe we can throw you some ropes to try to help you get out of the hole that you seem to have dug yourself into.
 
Saloon Keeper
Posts: 3336
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Junilu Lacar wrote:Here's an example of how I would have expected to see those methods I mentioned:

Look up new JavaDoc tags in Java 8: @implNote to see more examples.

I still have an issue with the impropriety of making Note a subclass of Notes.

Seeing as how the variable "activeNotes" is static, wouldn't this getter also be static?
 
Carey Brown
Saloon Keeper
Posts: 3336
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Status would be better implemented as an enum, rather than a String.
 
Carey Brown
Saloon Keeper
Posts: 3336
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
From JavaDoc for CopyOnWriteArrayList:
A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array.

This is ordinarily too costly, but may be more efficient than alternatives when traversal operations vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals, yet need to preclude interference among concurrent threads. The "snapshot" style iterator method uses a reference to the state of the array at the point that the iterator was created. This array never changes during the lifetime of the iterator, so interference is impossible and the iterator is guaranteed not to throw ConcurrentModificationException. The iterator will not reflect additions, removals, or changes to the list since the iterator was created. Element-changing operations on iterators themselves (remove, set, and add) are not supported. These methods throw UnsupportedOperationException.

It would seem that you are using this because you anticipate many concurrent threads accessing the List but having very few cases where a Note would be added or removed from the List. The problem that I see is that one thread may be going through an older version of the List very slowly and in the mean time another newer version of the List would be removing an item. Seems like each Note should have its own Status that can be set to DELETED when it's deleted from a new version of the List so that traversing an older version of the list can verify that the status is still ACTIVE before acting on it.

Edit: This would be in addition to your plan of taking the Note off the active list and putting it on the deleted list.
 
Dwayne Barsotta
Ranch Hand
Posts: 86
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The idea of using "CopyOnWriteArrayList<Note>" was I wanted a thread safe list.  Future coding will require me to write and read the data to and from a built in database.  As well as possibly changing the application from a single computer use model to a networked model where the the list may get accessed at different times.  If you look at the top of the notes.java class I have a comment "//I am not sure of this"  this is my note because I am not confident having a class object of notes that holds all the note objects.  I originally wanted to add the three:



at the top of the note class.  This way there was variables to hold all the notes in the given list.  How ever I read somewhere that using statics like this was "evil" so I was trying to find a way to group all the notes together.

As far as you making suggestions.  If you had a program where the dashboard had a section where a person can add individual notes, they would show in a list box.  the operator has a button where he can create a note, delete a note and archive a note.  As well as having a thread safe way to iterate through the list to do operations like update a database both internally and possibly externally.  Eventually the notes structure will need to accessed through connections from other clients, thus the thread safety.

How would you design this?  I don't need the code but in words, how would you design this type of system?

Thanks for your in site!  That is exactly why I posted this question.  As far as the note object understanding it's status, I did this but felt it was wasteful if I had lists of the notes based on the status.   
 
Junilu Lacar
Sheriff
Posts: 11496
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Dwayne Barsotta wrote:Notice on the test.java file, line 28 I used "for(Note note:note1.getActive()" to get all the active notes stored in the list.  There has to be a way I can reference these lists without going through the subclass objects.

I only got to this part after posting my other responses. At least you have some sense that what you did is smelly so that a good sign. This again is a consequence of the improper inheritance relationship you defined between Note and Notes.

One technique I wish was taught earlier and more widely is Test-driven development (TDD). It's a design technique that uses unit tests to drive the design decision making process. TDD almost forces you to write tests as essentially, experiments for how you'd use a class' API. It also has the advantage of keeping you in a very tight and disciplined development feedback loop and it makes you think about the consequences of every design decision that you make as you add small chunks of code and functionality to your program.

Some people think that TDD is something that beginners will find hard to comprehend but I think it's possible to introduce students to the concepts behind TDD and at least leave it as an option they can try if they feel up to the challenge. I taught my son how to do it when he started studying CS in college and he didn't seem too overwhelmed with the parts of TDD that I taught him. In fact, despite me not getting to give him as much tutoring as I'd like to give him, the few discussions I've had with him about the work he has done in his Java programming courses have shown that the little bit I showed him has had a lasting impact and has influenced his learning and development. I'm glad I taught him as much as he let me teach him, even though it was not even close to how much more I wanted to teach him.
 
Dwayne Barsotta
Ranch Hand
Posts: 86
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
After reading your post that you submitted as I was writing mine, I see I could eliminate the "notes" class and use a notes lists in the main program to hold references to all notes.

Then iterate through the list looking for what I need, like number active, total number.  Does that sound more acceptable?  When I want to know
 
Carey Brown
Saloon Keeper
Posts: 3336
46
Eclipse IDE Firefox Browser Java MySQL Database VI Editor Windows
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If your notes are backed by a database it seems like you should be using that to handle your concurrency. When you do a database query you get a snapshot back in a result set. As soon as a thread gets the result set it could potentially be out of date.

You might want to consider a "restful" approach where each record in your database has a unique id and a hash of its data. When you go to modify/delete a Note you'd have to pass the id and hash back to your DB layer to do a synchonized verify id and hash before performing the operation.
 
Junilu Lacar
Sheriff
Posts: 11496
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For me, thread safety is one of those things I keep in the back of my mind when I'm designing. It's not a concern that's in the forefront but something that I use as a loophole finder of sorts, in answer to the question that comes up after I have tested something that works conceptually and technically in single-threaded mode: "Now, that this seems like a pretty decent API, what could go wrong when we throw in concurrency?"

For me, a good and well-factored design that works well in single-threaded mode has a better chance of being able to handle concurrency or being easily refactored to do so. Trying to handle a complex and complicated concern like concurrency without the benefit of several rounds of refactoring first is often a recipe for disaster and getting into a vicious cycle of bad design decisions.
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!