''moved from ObjectsAndDataAreSeparate where MarkAddleman said:'' ''The key to an object is that it ''owns'' its state and no other object (or anything else) accesses that state without going through the contract.'' All an object is saying is it can provide information X or do behaviours Y. It is not making a statement about ownership. If I say I can get tickets to movie X am I saying I own the movie theatre or own the movie? No. I'm just saying I know how to get the tickets for you. If I say I can set the age of person, does it imply I own the age attribute? No, it just says I know how to set the age attribute. Lot's of other object may know how to do the same thing. -- AnonymousDonor (who is not CostinCozianu) Let's take a concrete example, a variant of your age example (I don't want to use age because the passage of time complicates the example unnecessarily, I think). Suppose we have setName and getName messages. What exactly is the object we're modeling and what are its requirements? If I'm modeling a Person whose responsibilities are simply to have a name and report it back, then I would not expect the name to change independent of calls to setName() on a particular instance. If I called aPerson.setName("Mark Addleman") and subsequently called aPerson.getName() and got back "Jon Doe" then I would consider that a bug. Specifically, that's a bug where somehow, I'm breaking encapsulation. However, if I'm NOT modeling a person, but a PersonNameAccessor, then the method signature would look something like void setName(Key personKey, String name); and String getName(Key personKey); Then, I no longer am concerned about encapsulating the person's behavior itself, but rather, the ''access' to that person's behavior. Thus, a call to setName(markAddlemanKey, "Mark Addleman") followed by getName(markAddlemanKey) returning "Jon Doe" may not be considered breaking encapsulation. Because I can't assume encapsulation, debugging a moderately large or larger program can become very difficult. Clearly there are problems with the example because I'm not considering multi-user access and whatnot. That's not the point. The point is, I generally don't want to model a PersonNameAccessor (particularly in the DomainModel), I want to model a person and the property of encapsulations allows me to assume away an entire class of bugs. The assumption doesn't always hold, but it holds often enough that I don't always have to be concerned about it. -- MarkAddleman ''If i say i can get tickets to movie X am i saying i own the movie theatre or own the movie? No.'' I agree with you. However, your contract implies that you have an association with either the movie theater or movie (perhaps both). What you ''own'' is that association to those other objects. It is this association that I would like to be encapsulated. I wouldn't want some other object to come along and somehow change that association between the time you make your commitment to me and the time you get to the theater. You could end up getting tickets for the wrong movie. --MarkAddleman ------ Mark, please consider the following ''broken encapsulation'' scenario: MarksAccount.getBalance(); // returns 100 ... MarksAccount.deposit(100); ... MarksAccount.getBalance() ; // returns 160 which is CORRECT - your wife might have withdrawn money from an ATM. This is correct because Account's balance can be modified only by two operations: increment and decrement. The two operations ''commute'' with respect to each other allowing a smart database manager to achieve correctness without exclusively locking the row (or object instance or whatever). Thus you don't have a perfectly encapsulated ''object'', but you have nevertheless a correct application. -- CostinCozianu ------ Costin, either you or I are missing the point. I ''think'' my point in all of this is that MarksAccount can only be modified through its contract. If that contract includes withdraw() ''and'' deposit(), then I agree with you, I (as an application programmer) have to consider the issue that getBalance() can return different results outside of a given user's manipulation of MarksAccount. That's concurrency management. What I ''don't'' have to be concerned about is CostinsAccount.deposit(1000) will somehow get into MarksAccount through some bug in the code. That's encapsulation. I believe that encapsulation and concurrency management are orthogonal issues. I could have a very elaborate locking or write-write detection mechanism and still have a bug where the deposit ends up in the wrong account. Likewise, I could have full encapsulation and not consider concurrency issues. -- MarkAddleman ---- Well said, Mark. I was about to contribute the following, but you beat me to the punch. ''This does not demonstrate lack of encapsulation if the wife's withdrawal is also accomplished by invoking a method on an instance of account representing Mark's (really, the Addleman couple's joint) account. However it does represent violation of encapsulation if the wife's withdrawal is accomplished by some other program (e.g., SQL*Plus in the hands of a DBA) executing "UPDATE ACCOUNT SET (BALANCE = BALANCE - 40) WHERE ACCOUNT_ID = ". --RandyStafford'' ---- I just read some of the discussion on the LiskovSubstitutionPrinciple (though I haven't read AlistairCockburn's paper yet and doubt I could follow it even if I did), but it occurs to me that we should define encapsulation as it relates to X and that might clear up the confusion. Encapsulation as I normally use the term (and others, I suspect) relates one object to all other objects in the system, but ''not'' to itself (although I've created enough boneheaded bugs to wish the system would encapsulate an instance from itself!). I think this relation is what gives rise to the difference between concurrency management and encapsulation. This might be a tautology, but here goes: I don't think you can ever have concurrency issues between two sets of well encapsulated objects where one set of objects has no association with the other set (and thus can't send messages to one another). --MarkAddleman Mark, my account getting confused with your account can't happen if you don't alter the PrimaryKey, but life is full of strange bugs. Let's focus here primarily on a pretty decent implementation without obvious bugs. From what was posted before ''object=data + behavior'', from where I interpret that encapsulation is this link between data (state) and behavior. Like you said in an OO system nobody should change the state of the object unless through its defined methods. So you can encapsulate state , preventing it from being directly changed by a method of another class, but you cannot prevent the ''state'' from being changed by a separate instance of the same class. Let's say you have an app sever and two separate transactions instantiate two separate instances that both reflect the same MarksAccount. Therefore, even if they have internally different states, they have the same logical states and they influence each other indirectly. So the encapsulation cannot be perfect as we are used to when let's say we program a GUI element where its internal state is desired to be safe and encapsulated. Furthermore the state can be altered by external systems that might not even be OO systems as Randy Stafford presented above. -- Costin ---- ''my account getting confused with your account can't happen if you don't alter the primary key'' Agreed. In the well-understood and somewhat trivial world of bank accounts, encapsulation probably doesn't buy us a whole lot. Particularly, if we assume a relational database backend (as opposed to FlatFile or dBase or something that doesn't easily support normal forms). However, for more complex domains such as modeling the relationships that banks have with their clients, the likelihood of bugs increases dramatically. ''Let's focus here primarily on a pretty decent implementation without obvious bugs'' I'm happy to go along with on this, but I do want to point out that assuming away bugs related to the lack of encapsulation is almost assuming the conclusion to this argument. ''Like you said in an OO system nobody should change the state of the object unless through its defined methods. So you can encapsulate state , preventing it from being directly changed by a method of another class, but you cannot prevent the ''state'' from being changed by a separate instance of the same class. '' I'm not sure I understand what you mean here. Do you mean something like (in Java): public class ViolatesEncapsulation { private String name; public void setName(String name) { if (name.equals("test")) throw new IllegalArgumentException(); this.name=name; } public boolean violate(ViolatesEncapsulation other) { other.name = "test"; } } While I suppose this is true, you'll be hard pressed to convince me that this problem is large enough to be worth dumping the concept of encapsulation entirely. Furthermore, SmalltalkLanguage forbids this (technically, SmalltalkConvention''''''s forbid this, but that's another story). ''Let's say you have an app sever and two separate transactions instantiate two separate instances that both reflect the same MarksAccount. Therefore, even if they have internally different states, they have the same logical states and they influence each other indirectly. '' This is exactly one example of the fallacy of ObjectRelationalImpedanceMismatchDoesNotExist. GemStonej, Voss, and other ObjectOrientedDatabase''''''s (by the way, I understand why people would prefer the term PersistenceEngine) ''ensure'' that this situation never happens. I don't particularly care how they implement this guarantee, but I know that they do. What you describe is, in fact, a real problem if you use a RelationalDatabase and that's why I don't (or try not to). This is the problem because RelationalHasNoObjectIdentity, however ObjectOrientedDatabase''''''s (or PersistenceEngine''''''s) do. -- MarkAddleman That's the fallacy of your own psychological ImpedanceMismatch. Gemstonej will never give you the transactional performance of Oracle, nomatter how hard they try. In addition ObjectOrientedDatabase''''''s are in violation of DatabaseApplicationIndependence, therefore they '''are''' only PersistenceEngines. What I described is not a problem at all. It performs correctly and accurately, conforms to SeparationOfConcerns (it should not be an application developer job to think of what locks and what type of locks he should request, or even to know what type of concurrency control algorithm is being used by the database). More, it has demonstrably much higher transactional throughput and greatly reduces the chances of transaction deadlock. -Costin If you want to shoot yourself in the leg though, you can also do it with a relational database, just like I described in RelationalHasNoObjectIdentity ----- ''Gemstonej will never give you the transactional performance of Oracle, nomatter how hard they try'' That may be, I don't really know. I don't particularly care. GemStonej gives me and my clients acceptable runtime performance. Furthermore, it gives me and my clients superior development performance (ie - I can develop applications faster with it than with Oracle). Perhaps this is because my thinking is muddled and RelationalDatabase''''''s are the OneTrueWay, but I tend to doubt it and you have yet to convince me. ''it has demonstrably much higher transactional throughput and greatly reduces the chances of transaction deadlock'' If the crux of your argument is that I should dump encapsulation and ObjectIdentity because of performance reasons, then I simply reject that argument. Not because your argument is flawed, but because I don't care that much about performance and GemStonej's performance is GoodEnough. More importantly, it's good enough for my clients who care about getting their application up and running quickly. Furthermore, OptimizeLater tells me that I should first get their application up and running quickly and then focus on performance. '''' ''If you want to shoot yourself in the leg...'' You seem to imply there is some downside to object identity other than performance. I don't know what it is and having read RelationalHasNoObjectIdentity again, all I find are assertions not rationales and some reference to "internal identity" that I don't really understand. -- MarkAddleman ---- To be clear, I contend that if I submit to the constraints that ObjectIdentity and encapsulation present, I can code an application more quickly than if I have to worry about the issues that present themselves if I release these constraints. Given that I choose to submit myself to those constraints, using tools that enforce those constraints will help me from accidentally straying from those constraints and thus help avoid the 'non-constraint' issues. The tools that I choose to use are ObjectOrientedLanguage''''''s and ObjectOrientedDatabase''''''s. Finally, I contend that someone can provide an isomorphic mapping between a TuringMachine and my choice of programming environment so I don't lose any power and I gain the convenience of assuming away an entire class of bugs. -- MarkAddleman Mark, if you are assuming that object identity and encapsulation is all you need to have a correct behaviour under concurrent transactional access to data you're wrong. There are logical constraints that span a single object state, therefore cannot be resolved by object encapsulation. To deal with these constraints you have to think of them in ''logical'' terms (equations if you want) as you can do within a relational model, and not in algorithmic terms like you do in OO languages. This is why I asked below once again if Gemstone only detects write-write conflicts, they are not the only logical concepts that can happen in concurrent data access. -- Costin ''I am not assuming that object identity and encapsulation are all that's needed for AtomicConsistentIsolatedDurable transactions. The classic BankAccountTransferProblem refutes that. My claim is that object identity and encapsulation are '''useful''' concepts in their own right and I am more productive if I use tools enforcing/supporting those concepts. ACID transaction concurrency is also a useful concept in certain problem domains, but orthogonal to object identity and encapsulation which, I believe, have a wider use. Fortunately, I don't have to give up object identity and encapsulation to gain ACID transactions. See GemStonejConcurrencyMechanism for a description of what it provides.'' ----- Well, if you care only about performance in development and don't care that much about transactional throughput maybe GemstoneJ is the right tool for you. Especially since you're comfortable with it and uncomfortable with Oracle. However this doesn't mean you can assert an ImpedanceMismatch, rather a psychological mismatch. Others might be able to have quick development with Oracle nevertheless. That's what I'm trying to say. I also have a big psychological mismatch with VisualBasic, however I don't blame VisualBasic for that, and I admit other people can do a great job with it. But just because you said you'll optimize it later. What if later you or your current company (assuming that you program for a customer) won't be there? Somebody else may want to come and extend the system, or just fix a damn thing. If the best solution would be to write something in C, then they are out of luck. That means you locked your customer in, to your domain of expertise. If you would have developed with Oracle, I might have come later and do something in Scheme if it so pleases me. That is what the DatabaseApplicationIndependence principle is for. And if only the earliest transaction is allowed to win, and the others are aborted, what if a particular workload pattern does not favour this particular policy (any valid concurrency control policy is a design trade-off that might suite particular class of applications but not others), what do you optimize then ? --CostinCozianu < deleted some comments irrelevant to this discussion > ---- I find a lot of references to Gemstone and how you can develop fast and that it runs fast. As a reference - what is the volume of the data ? volume of objects ? what would that match in a relational database ? JanNilsson ---- CategoryConcurrency