Free software is a matter of liberty, not price.
There are already simply, preexisting structures out there(Hashmaps, treemaps, etc.,) that could serve the same function as your LockManager.
Instead of creating your own static data structure, why not simply using a static Map?
Max, could you clarify your point, please?
I had an impression that many of us shared an opinion that a separate class such as LockManager that contains a collection of locks is a sound solution. Do you disagree with that?
Instead of creating your own static data structure, why not simply using a static Map?
Doesn't the static map limit you to only one database?
Eugene.
My first comment is that your unlock doesn't seem to check the credentials of the locking client, per the instructions, so that's probably not good.
Instead of creating your own static data structure, why not simply using a static Map?
Free software is a matter of liberty, not price.
Originally posted by Raffe Paffe:Max,
---My first comment is that your unlock doesn't seem to check the credentials of the locking client, per the instructions, so that's probably not good.
Hmm, I don't understand this. What do you mean? What credentials?
---Instead of creating your own static data structure, why not simply using a static Map?
Do you mean that I should put the implementation in Data and make lock/unlock synchronized in Data?
But what should I put in the Map? I have only one Data object in my system so i cant track clients.
Thanks alla for looking at my stuff.
Raffe
If I'm not mistaken, your unlock method requires that only the client that originally locked the record be allowed to unlock it.
Free software is a matter of liberty, not price.
A cornerstone of OO design is that a coherent and well-conceived class should do one thing, and do it well. It is easy to argue that the locking code is sufficiently complex and orthogonal to the other concerns of the Data/RemoteData/Connection class that a separate class is justified. This can also make sychronization cleaner. These arguments are quite independent of whether that class will be reused or not, or whether there will be more than one database.Instead of creating your own static data structure, why not simply using a static Map?
Or, in the opinion of some much better, thuslyThis is more expressive of the fundamental properties of the record locks that you can only have one such lock outstanding per record.[...] lock thusly
It bears mentioning that many have argued that the empty implementations in the Data class itself are fine as they are (I'll leave the reasons why as an exercise for the reader), and implemented full lock() and unlock() functionality only in another class, the networked version of Data. Many passed with outstanding scores.Yes, I think you should put the implementation in Data.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Free software is a matter of liberty, not price.
Originally posted by Peter den Haan:
Making any of the locking data structures static is unambiguously a mistake;
It bears mentioning that many have argued that the empty implementations in the Data class itself are fine as they are (I'll leave the reasons why as an exercise for the reader), and implemented full lock() and unlock() functionality only in another class, the networked version of Data. Many passed with outstanding scores.
Max Habibi wrote:
However, in the current exam, there are must sections, which state that the direction therein must be explicitly carried out, or the student will automatically fail.
So were there in older versions of the exam. But don't get too hung up on the particular version I did -- I've been hanging around here for ages now, moderated the forum for a fair while, and am reasonably familiar with a number of iterations of the exam.Originally posted by Max Habibi:
Peter, I know that you took a much earlier version of the exam, so the requirements may have been different. However, in the current exam, there are must sections, which state that
the direction therein must be explicitly carried out, or the student will automatically fail.
I believe I was quite moderate in tone; contemplating alternative perspectives doesn't hurt anyone -- especially not in this assignment. And as far as I'm aware, I have as much right to offer my perspective in this thread as you have to give yours.You seem to have very strong views on this issue, some of which, if I understand them correctly, I disagree. In the interest of keeping the tone of the current thread moderate, please help me by arguing your prespective on another thread.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Originally posted by Eugene Kononov:Originally posted by Eugene Kononov:
I'd like to point out that OO design is also a must,
Originally posted by Peter den Haan:
So were there in older versions of the exam. But don't get too hung up on the particular version I did -- I've been hanging around here for ages now, moderated the forum for a fair while, and am reasonably familiar with a number of iterations of the exam.
Don't get too hung up on length of moderation time Peter. I've been helping people a while too, and I think I'm starting to see a dangerious tread here, where people are starting to feel that there's only one valid approach to the scjd. This is utter nonesense, of course, and not a moderate view at all.
I believe I was quite moderate in tone; contemplating alternative perspectives doesn't hurt anyone -- especially not in this assignment. And as far as I'm aware, I have as much right to offer my perspective in this thread as you have to give yours.
- Peter
Originally posted by Raffe Paffe:
Max,
First, thanks for posting. I have changed my lock/unlock for a week now and I am a litle frustrated. I am NOT
getting something here. :-(
This is my design.
I have a RemoteDataImpl object and LocalDataImpl that implements DataInterface(with all the methods in Data).
My client gets a new RemoteDataImpl for each client. The RemoteDataImpl has a Data object. Theire is only one Data so they all
have the same.
In Data i have lock(int recno) and unlock(int rec).
So, I can use RemoteDataImpl to track the client since every client got its unique RemoteDataImpl, but how can i get it into
Data if i only have lock(int recno) and unlock(int rec)? This part i dont understand.
I use to have a lockmanager in RemoteDataImpl that had lock(this,recno) and that worked but as said in the instructions;
you must implement the lock/unlock in Data. So i moved it.So again how do i get the RemoteDataImpl into Data?
Reading your comment again, i wonder of the difference between Data and RemoteData in your comment? Is it as my design RemoteDataImpl and Data or is it the same class??
Where does it says this?I cant find it anyware!?
Is my thinking and design correct?
Sooo... given that every single point I addressed was relevant to the original question, how do you as a moderator of this forum define "hijacking a thread"? Expressing an opinion that doesn't agree with yours?Originally posted by Max Habibi:
Not only do you have a right Peter, you have an invitation from me personally: However, you don't have the right to hijack this thread, as I define hijacking a thread.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Originally posted by Peter den Haan:
Sooo... given that every single point I addressed was relevant to the original question, how do you as a moderator of this forum define "hijacking a thread"? Expressing an opinion that doesn't agree with yours?
Or, perhaps, a thread gets hijacked when you start to turn contrasting views into a personal discussion such as the one we're engaged in right now instead of leaving it to Raffe to make up his own mind? You know, I specifically tried to formulate my response in such a way as to avoid exactly this -- by using phrases such as "in the opinion of some" -- yet it is you who can't leave well alone and accuse me of "hijacking" and acknowledging "only one valid approach". This is a complete perversion of the truth.
- Peter
I couldn't agree more. I can't wait to junk all the excess baggage, and discuss stuff relevant to the locking design, such as tracking client identity (now that's at least something we all agree on), whether locking ought to be factored into a separate class, synchronization, modeling the lock/client relationship (which is N:1, set:collection on the problem domain level), modeling the local file/lock set/client relationship (1:1:N), and so forth.Originally posted by Taariq Levack:
please guys, i opened this thread expecting a discussion on lock/unlock, not a scene from some soap opera, move it to another thread as lots of this discussion has nothing to do with locking/unlocking, and is a waste of my time, effort and already limited bandwidth
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Looks absolutely great so far.Originally posted by Raffe Paffe:
I have a RemoteDataImpl object and LocalDataImpl that implements DataInterface(with all the methods in Data).
My client gets a new RemoteDataImpl for each client. The RemoteDataImpl has a Data object. Theire is only one Data so they all
have the same.
The problem you have here is an expression of the fact that you're trying to mix up the concerns for local, single-user database access with those for networked, multi-user access. Remember the one responsibility rule.In Data i have lock(int recno) and unlock(int rec).
So, I can use RemoteDataImpl to track the client since every client got its unique RemoteDataImpl, but how can i get it into
Data if i only have lock(int recno) and unlock(int rec)? This part i dont understand.
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Free software is a matter of liberty, not price.
Originally posted by Peter den Haan:
The problem you have here is an expression of the fact that you're trying to mix up the concerns for local, single-user database access with those for networked, multi-user access. Remember the one responsibility rule.
Upon reflection, my conclusion was and is that the implementations in Data as supplied are just fine the way they are (i.e. empty) and satisfy the requirements in every way (which in this regard haven't really changed over the years). After all, in the absence of any other competing clients they correctly implement the contract for lock() and unlock() as specified by the javadoc for these methods.
This, I believe, is both the simplest possible implementation of the requirements and the most natural solution for the problem.
If this doesn't convince you and you are of the opinion that the instructions require you to put all of your locking code in Data itself, you have two problems on your hands. The first is: how do you get useful locking semantics when dealing with Data alone, i.e. in local mode? The second is the one you mentioned: how do I communicate my client ID?
You can kill both birds with one stone[1] by changing the signature of the lock() and unlock() functions. I think we all agree this would be a mistake.
You could solve the second problem by making RemoteData a Data subclass and implement your locking there. By making the lock map static, all Data subclasses still share the same locks. This design would be deeply wrong for a number of reasons. RemoteData would need to override virtually all methods without delegating them to its Data base class;
this is not merely a code smell, it is an overwhelming code stench if there ever was one. In this design at least, RemoteData IS-NOT-A Data and should not have an inheritance relationship. The static lock map introduces an inappropriate Singleton;
one sign of this is that you suddenly get funny restrictions, such as only ever being able to use one database file per JVM -- your colleagues coding the rest of the system, or enhancing it in the future, will be very pleased when they find this out (do, however, not identify this consequence as the reason why the singleton is inappropriate; it is just one consequence of a fundamental design flaw). On top of all this, it doesn't address the first problem in any way.
Another approach for the second problem could be to add new package-private lock() and unlock() methods which take a client ID. They would sit a bit uncomfortably next to the client-visible lock() and unlock() (another code smell, but you might judge it to be a bearable one); it would work though. The locks could simply be an instance field of Data in that case.
On the other hand, implementing something doesn't mean the implementation cannot delegate to another class -- after all, you can implement locking yet delegate most of the hard work to a class like HashMap, so why wouldn't you be able to leave most of the sweating to a LockManager if the problem demanded a design like that? Both Data and RemoteData could delegate to a private LockManager instance. Data would not need any additional methods unrelated to its core function, or modifications in method signatures.
That still leaves the first problem: what does locking mean for Data itself? What are different clients in the context of a local database? The only reasonable suggestion I've ever seen in the many discussions is to use the current Thread as the client identifier. There are however three problems with this. First, the javadoc does not even hint at this; admittedly, they don't hint at pink elephants either but in contrast to pink elephants, you would expect such a concept of identity to be documented there. Second, this only works outside an RMI context; I understand everyone is now in agreement on this. Finally, it would mean radically different semantics for lock() and unlock() in local mode vs. remote mode. This, again, seems wrong. If two classes implement the same interface, they should really implement the same semantics for the methods in that interface; all else dilutes the significance of the interface and introduces the potential for subtle and not-so-subtle problems. If different threads would need to embody different clients, they should get different DataInterface implementations (a RemoteData or similar, but used locally).
In conclusion, it would seem that implementing locking inside Data itself quickly leads you into a quagmire of contradictions, complexity, arbitrary restrictions and plain old bad design.
However there are no doubt alternatives that I have missed. Max? You seemed to have another alternative in mind, one where each client has its own copy of Data? Can you elaborate?
As a final word, I'd like to add that I don't believe for a moment that Sun intended their instructions to stand in the way of good design and industry best practice. If you find that this is the case, you are either doing something wrong in your design or interpreting the instructions in a way they were never meant to be.
You are too kind. Unfortunately, I have no recollection of doing anything other than trying to focus on the issue at hand. But let's allow this matter to rest.Originally posted by Max Habibi:
Peter, since you seem to be making a effort to focus your points to the issue @ hand, I'm going to let this thread continue for a bit.
So you think Sun's intention is for you to put the code in the Data class, even though it serves no purpose there, and is related to another class altogether?Peter is correct that in local mode, no competing clients should be expected [...] However, I read to requirements as stating the lock and unlock be implemented in Data, so my feeling is that, regardless of where it is used, that is what Sun wants to see.
Anything satisfying the javadoc contract is a valid implementation of the requirements -- if that's a no-op implementation, great. That's polymorphism for you. You get exactly the implementation you require.However, this is not the same argument as saying that they actully do implement something when they are, in fact, empty!
They all have to delegate to a shared Data instance, eventually. Actually, this is not strictly true; there's been one participant in this group who got everything to work with multiple File objects and Data instances over the same disk file. Not pretty, not necessary, and not an approach I would advocate.Peter, I'm a little confused on why you think this is true? Not that I advocate the approach of extending Data, but why do you think the extended class would have to re implement all of it's methods?
I'm leaving the rest as an exercise for the reader. In particular, there is a three-point test in the article which helps you determine whether you are really looking at a Singleton. Anyone reading this can follow the link and do the test. The wiki link intelligently discusses various takes on the purpose behind Singletons, when to use them, and when not to use them. I don't think a full-blown discussion in this group would be productive at this point.This is a correlative argument, not a causical one. Putting the HashMap next to an ibm link that suggest that sometimes, some singletons are bad is not a conclusive logical tactic.
Aren't they? What we are building in the assignment is quite evidently only a fragment of a system. Another subsystem will have to read the flights table and... well... given the restrictions you built into it, they have to develop all their other database needs from scratch as they can't use your Data stuff.However, since [your colleagues] are not required to [build the rest of the system, or extend FBN] right now [...]
No it isn't, and I'm sure I stated as much earlier. Of course, all things being equal, the fact that a LockManager is much more amenable to re-use is a very good thing, but that's not the main point.Why use a lockmanager? Reasons for doing so are the expectation of future functionality
Oh no, please, not again -- it's getting tired now. I did highlight in some detail a fair number of significant problems and questions which crop up when you try to stuff locking into Data. When I then conclude that there are problems associated with this choice (ok, so I used more colourful language), it is little more than a summary of what has come before; you cannot simply dismiss this as a "statement". It's high-handed assertions like yours here that make rational discussion derail time and time again. Please don't.Actually, this is not a conclusion Peter, it's a statement.
Now there's scope for some focused discussion. If there's a single Data, what do you gain by making the lock manager static?[...] That is, by all means, use a single class, shared by all instances of RemoteData keep track of Locks: but use a static HashMap that is a member variable of Data
I'm not sure that I favour "more full bodied solutions" -- but I do attach great importance to the relation between the object model and the problem domain, and observe that when you get that right you often end up with more flexible, easier to understand and maintain designs without increased complexity. I do also think that for many, the Developer's exam is one of the rare opportunities to pursue that goal to a greater extent than they would normally be able to do; and that, when you take the trouble to do this, you will come out as a much better designer and developer. On the other hand, there's no way I would promote features beyond the scope of the assignment for their own sake[1].I seem to favor it towards limiting scope and coding rigiously to the specifications. You seem to favor more full bodied solutions. Can we agree that there is more than one valid way of addressing this problem?
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
You are too kind. Unfortunately, I have no recollection of <snip>
quote:
--------------------------------------------------------------------------------
Peter is correct that in local mode, no competing clients should be expected [...] However, I read to requirements as stating the lock and unlock be implemented in Data, so my feeling is that, regardless of where it is used, that is what Sun wants to see.
--------------------------------------------------------------------------------
So you think Sun's intention is for you to put the code in the Data class,
Yes, since that is exactly what they ask you to do.
even though it serves no purpose there, and is related to another class altogether?
Peter, this is just your opinion, no matter how strongly you feel it. I feel that it does naturally belong there, and I feel that the requirements are explicit on this point when they say: "you may implement(lock/unlock) in two ways. by modifying the Data class or extending it"
I guess this is the point where rational argument ends
rational argument only ends when one or both of the parties choose to ignore it. The requirements are explicit and clear to me. "you may implement(lock/unlock) in two ways. by modifying the Data class or extending it". This may not be convincing argument to you, but it is rational. I'm surprised that you don't see this.
and we just have to let the respective opinions stand. It is beyond my belief that in an assignment which is to a significant extent about design, those bright people at Sun require you to compromise your design to such an extent.
Yes, if it had been objectivity agreed that such is a design compromise. However, that is a subjective opinion(yours), and thus not compelling. It like to see an objective argument that doesn't resort to pejoratives like 'natural', 'better', 'stench', etc. So far, I have not.
It seems to me that reading the instructions as requiring that all the locking code reside in Data itself is reading many more constraints into them than are actually there.
That is the point of specifications, to provide a guide that will serve as a literal interpretation.
quote:
--------------------------------------------------------------------------------
However, this is not the same argument as saying that they actually do implement something when they are, in fact, empty!
--------------------------------------------------------------------------------
Anything satisfying the javadoc contract is a valid implementation of the requirements -- if that's a no-op implementation, great. That's polymorphism for you. You get exactly the implementation you require.
The javadoc requirements, in addition to the explicit requirements that lock and unlock be implemented in Data or some extended class do not indicate this.
quote:
--------------------------------------------------------------------------------
Peter, I'm a little confused on why you think this is true? Not that I advocate the approach of extending Data, but why do you think the extended class would have to re implement all of it's methods?
--------------------------------------------------------------------------------
They all have to delegate to a shared Data instance, eventually. Actually, this is not strictly true; there's been one participant in this group who got everything to work with multiple File objects and Data instances over the same disk file. Not pretty, not necessary, and not an approach I would advocate.
This indicate that you're missing the point entirely. Each client has their own Data instance in the design I advocate.
quote:
--------------------------------------------------------------------------------
This is a correlative argument, not a causical one. Putting the HashMap next to an ibm link that suggest that sometimes, some singletons are bad is not a conclusive logical tactic.
--------------------------------------------------------------------------------
I'm leaving the rest as an exercise for the reader.
yes...
quote:
--------------------------------------------------------------------------------
However, since [your colleagues] are not required to [build the rest of the system, or extend FBN] right now [...]
--------------------------------------------------------------------------------
Aren't they? What we are building in the assignment is quite evidently only a fragment of a system.
I'm not sure what quite evidently means Peter: do you mean that there is some evidence to indicate this? If so, I'm not aware of it. However, that is beside the point here, and I think you are aware of this.
Another subsystem will have to read the flights table and... well... given the restrictions you built into it, they have to develop all their other database needs from scratch as they can't use your Data stuff.
Again, these fictional colleagues and fictional database don't exist in the world of the application, so it think it's folly to design for them. It's just as reasonable to assume that the system will serve business need sufficiently, or that the whole paradigm will be replaced in the future.
But let's not get drawn into this discussion again. As I indicated, it is just one consequence of a fundamental design flaw.
You did indicate this, but you have failed to substantiate that statement. But by all means, lets not get drawn into this again.
There are more important matters, such as the role of Singletons in software design.
Is this the issue that you 'left as a exercise'? Are you really indicating that a discussion you refuse to have(hopefully, on another thread) is the winning point of this argument?
quote:
The main point is that it is a coherent set of concerns that are sufficiently different from and orthogonal to the other responsibilities in the (Remote)Data class to be refactored into another class.
Ok, good. Now please defend this statement, without resorting to fictional future requirements, in light of the fact that the specifications explicitly state that lock and unlock need to be implemented in Data.
--------------------------------------------------------------------------------
Actually, this is not a conclusion Peter, it's a statement.
--------------------------------------------------------------------------------
Oh no, please, not again
The question has failed to be answered, and thus needs to be asked again.
-- it's getting tired now. I did highlight in some detail a fair number of significant problems and questions
But you did not.
which crop up when you try to stuff locking into Data. When I then conclude that there are problems associated with this choice (ok, so I used more colourful language), it is little more than a summary of what has come before; you cannot simply dismiss this as a "statement". It's high-handed assertions like yours here that make rational discussion derail time and time again. Please don't.
This is ridiculous on the face of it, and I expect better from you Peter. You have make unsubtaited statements, then used those to draw a 'conclusion' which 'proves' your point. Please, I know you can reason better then this.
quote:
--------------------------------------------------------------------------------
[...] That is, by all means, use a single class, shared by all instances of RemoteData keep track of Locks: but use a static HashMap that is a member variable of Data
--------------------------------------------------------------------------------
Now there's scope for some focused discussion. If there's a single Data,
--------------------------------------------------------------------------------
I seem to favor it towards limiting scope and coding rigiously to the specifications. You seem to favor more full bodied solutions. Can we agree that there is more than one valid way of addressing this problem?
--------------------------------------------------------------------------------
I'm not sure that I favor "more full bodied solutions" -- but I do attach great importance to the relation between the object model and the problem domain,
There is certainly more than one way to skin this particular cat[2], and on many occasions I've helped ranchers along paths that were quite different from my own. But there are also ways that the cat really shouldn't be skinned -- certainly not if that comes in the form of firm and authoritative advice from an author and moderator.
[1] The sole exception was that, like you, I used to promote lock cleanup simply because it was so laughably easy to do; after all the discussions we had lately, I'm no longer convinced that this is such a good idea unless you really know what you're doing.
Now, since each GUI client has their own RemoteDataImpl object, and each RemoteDataImpl in turn has their own Data, then in effect, each GUI client has their own Data object.
If this -- right next to each other -- is what it says these days[1], then it is unambiguous that Data must have some sort of non-empty locking implementation. Not that this would preclude delegation.Originally posted by Max Habibi:
you may implement(lock/unlock) in two ways. by modifying the Data class or extending it"
Peter den Haan | peterdenhaan.com | quantum computing specialist, Objectivity Ltd
Originally posted by Eugene Kononov:
... would become
Something like that? That is, sprinkle the methods of Data with the critical sections? Is that the approach that you advocate?
Eugene.
[ April 01, 2003: Message edited by: Eugene Kononov ]
Max wrote:
Not exactly Eugene: It is the responsibility of the client to lock, modify, and then unlock, just as most most databases do(you can have transactions support or you can not have it).
However, I'm happy to send it to you personally( since you've already passed), along with the suggested implementation of lock/unlock if you like. Would that be convincing?
Actually, my opinion on this matter is that somewhat similar to yours, except that is less complex, IMO.
That is, by all means, use a single class, shared by all instances of RemoteData keep track of Locks:
but use a static HashMap that is a member variable of Data, not a LockManager that resides outside of the class.
This fufils all of the requirements of the exam nicely, and provides a straight forward implementation.
Free software is a matter of liberty, not price.
Originally posted by Raffe Paffe:
If I understand this comment correct you are saying that every client has a RemoteData and all
RemoteData have(share?) the same Data object. Implement a HashMap in Data and keep your
client id and lock number in that HashMap.
Again, I want to emphasize that I think that Peter's solution is a good one: it's just best (for you) to consider both options, understand them well, and decide which you want.
Free software is a matter of liberty, not price.
Free software is a matter of liberty, not price.
The Sun Certified Java Developer Exam with J2SE 5: paper version from Amazon, PDF from Apress, Online reference: Books 24x7 Personal blog
If you are running on a virtual machine that does not implement pre-emptive multitasking,
then your locking method could block the other threads from completing.
I think you should put back your calls to wait() and notify() so that other threads
(and other applications) can get some of the CPU.
Eugene :
Is what Raffe Paffe posted really your code, from the book or some other source?
Is that what you recommend?
Free software is a matter of liberty, not price.
Originally posted by Eugene Kononov:
Max,
Is what Raffe Paffe posted really your code, from the book or some other source? Is that what you recommend?
Eugene.
Barry's not gonna like this. Barry's not gonna like this one bit. What is Barry's deal with tiny ads?
Smokeless wood heat with a rocket mass heater
https://woodheat.net
|