home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / lang / cplus / 11359 < prev    next >
Encoding:
Text File  |  1992-07-22  |  10.2 KB  |  292 lines

  1. Path: sparky!uunet!mcsun!fuug!demos!kiae!glas!demos!ucc.su.oz!extro.ucc.su.OZ.AU!maxtal
  2. From: maxtal@extro.ucc.su.OZ.AU
  3. Newsgroups: comp.lang.c++
  4. Date: 18 Jul 92 16:04 MDT
  5. Subject: Re: many set/get member functions in a 
  6. Sender: Notesfile to Usenet Gateway <notes@glas.apc.org>
  7. Message-ID: <1992Jul18.120442.20292@ucc.su.oz>
  8. References: <1992Jul08.121838.13948@jho.com>
  9. Nf-ID: #R:1992Jul08.121838.13948@jho.com:2043735141:1992Jul18.120442.20292@ucc.su.oz:1800623228:001:9947
  10. Nf-From: extro.ucc.su.OZ.AU!maxtal    Jul 18 16:04:00 1992
  11. Lines: 279
  12.  
  13.  
  14. In article <9220019.7137@mulga.cs.mu.OZ.AU> fjh@mundil.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
  15. >maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller) writes:
  16. >
  17. >>>Programmers are notorious for making unwarranted assumptions:
  18. >>
  19. >>    Agreed. So the assumptions the programmer DOES make should
  20. >>be PUBLIC and ADVERTISED. It is part of the contract between
  21. >>the class and the user.
  22. >
  23. >I would much rather the the programmer NOT make them in the first place,
  24. >if this is possible. 
  25.  
  26.     I dont understand.
  27.  
  28.     The assumptions about the form of a class ARE the class semantics.
  29.     Mathematically, they ARE the axioms of the type.
  30.  
  31.     Having a well defined interface is only PART of the semantics.
  32.  
  33.     For example, an object with + and * by scalar defined is NOT
  34.     yet a vector: you need to add the distributive law:
  35.  
  36.     a(b+c)=ab+ac
  37.  
  38.     The problem in C++ is you say about + and * but not the
  39.     fact that there IS a distributive law. Any class derived
  40.     from vector MUST have + and * defined, and the language
  41.     enforces that.
  42.  
  43.     It also must define + and * to obey the distributive law,
  44.     and the language CANNOT enforce that. 
  45.  
  46.     Modern computer science would LIKE to enforce the semantics,
  47.     but it is like the halting problem: it cant be done in general.
  48.  
  49.     So it is up to you the programmer to do it.
  50.  
  51.     In the case of C++ there is ONE case only that you can do it.
  52.     That is where some component is unconstrained.
  53.     A public variable of that component type GUARRANTEES that
  54.     that it be unconstrained.
  55.  
  56.  
  57. >And get/set functions do allow that.
  58.  
  59.     Yes, they void the guarrantee.
  60.  
  61. >>    Wrong argument. IF someone wanted to change that function,
  62. >>I woudl sure want to know about it, because my whole
  63. >>program RELIES on the ability to just set and get wages.
  64. >
  65. >But I am not going to take that ability away!
  66.  
  67.     But you JUST DID. You can change get and set and my routines
  68. will still compile with yours---they just won't work.
  69.  
  70.     The boss will blame ME. When I find out you screwed up
  71. I will have your hide. It will cost you at least one shout at the pub :-)
  72.  
  73. >I *do* want to be able to redefine the effects of calling get/set if the
  74. >specification changes.
  75.  
  76.     NO. If the specification changes, and you change the class
  77. semantics you want EVERY use of the class to FAIL TO COMPILE.
  78.  
  79.     I do this REGULARLY. I change the NAME of the function
  80. to one I haven't used before. Then I recompile everything.
  81. Wherever the cursor stops on the old name, I examine the
  82. code and context and change to the new one IF and ONLY IF
  83. the change is transparent.
  84.  
  85.     *I* have to do this because the compiler cant.
  86.  
  87.     Lets not get confused: changes to implementation OUGHT
  88. to be transparent, changes to semantics OUGHT to be opaque.
  89.  
  90.     In C++ you can *almost* hide implementation details.
  91.     Unfortunately, the BEST the language can do to advertise
  92. semantics is to advertise the interface. That is not good enough.
  93. [The rest is traditionally done with comments]
  94. To say that is what you want is to completely misunderstand the
  95. purpose of compile time guarantees.
  96.  
  97.     The fact is you only THINK you know what you are doing.
  98. I often THINK I know what I am doing and the compiler tells me
  99. I dont. It is *almost* always right.
  100.  
  101. >>    This is NOT NOT NOT a change in implementation. THIS IS
  102. >>A CHANGE IN SEMANTICS. Conversely to your argument, the big
  103. >>problem in C++ (among other languages) is that this sort of
  104. >>tampering CANNOT be prevented. In a "real" language the semantics
  105. >>would be specified and your program would fail, it would
  106. >>dial the police and have you arrested for interfereing with the
  107. >>payroll.
  108. >
  109. >In any real-world program, the specifications will change which will require
  110. >you to change the semantics. Attempting to prevent these sort of changes
  111. >is counter-productive.
  112.  
  113.     No, the system should not prevent you changing the semantics.
  114. Of course not. IT SHOULD make sure that ALL the ramifications of
  115. the changes are examined before you make some silly half arse
  116. ill-considered changes. It cant actually do this of course.
  117.  
  118.  
  119.     But you want the opposite: you want to be able to change
  120. the semantics PRIVATELY. One view of programming with classes
  121. is called CONTRACT programming: each class and user of the class
  122. makes guarrantees and in returns takes on certain
  123. responsibilities.
  124.  
  125.     That arrangement: the CONTRACT, IS the semantics.
  126. The contract is PUBLIC. If you go and change the effect
  127. of some set function you are BREAKING the contract.
  128. So then my code won't work. This is not allowed.
  129.  
  130.     Instead you must REWRITE the contract. To do that
  131. you must rope in and obtain all concerned. ALL the users
  132. of the class must agree. INCLUDING my piece of code,
  133. which relied on certain semantics from your class.
  134.  
  135.     So, if you really want to change the contract
  136. you better tell me. Even better, the COMPILER should tell
  137. me.
  138.  
  139.     IT DOES if that change involves a change in the
  140. interface (Good). It doesn't if the meaning but not
  141. the interface changes. (bad).
  142.  
  143.  
  144. >
  145. >>    Why: well, how about:
  146. >>
  147. >>    set_hourly_wage(double wage){hourly_wage=wage*10.0;}
  148. >>    get_hourly_wage(){return 20* hourly_wage;}
  149. >>
  150. >>See: you can't tell me THAT isn't a change in SEMANTICS!
  151. >
  152. >Yes, but now you have broken a promise that was implicit in the class interface.
  153.  
  154.     Of course. Exactly. EVERY CHANGE IN MEANING NECESSARILY
  155. BREAKS SOME PROMISE whether implicit in the class interface
  156. or not.
  157.  
  158.     AND IN THE CASE OF PUBLIC VARIABLE THE PROMISE IS EXPLICIT
  159. AND THE COMPILER WILL NOT LET YOU CHANGE THE SEMANTICS.
  160.  
  161. >(At least for English-speaking programmers. If the methods had been
  162. >void blurhf_wage(double wage) and double sqlop_wage() then the above change
  163. >would not be breaking any promises.)
  164.  
  165.     But if the VARIABL were public and called X7163 or WKhjdusjk
  166. the promise woudl STILL BE BROKEN AND STILL CAUGHT BY THE COMPILER.
  167. GET IT: THIS IS A GUARRANTEE. ONE OF THE FEW. It does not depend
  168. on you ability to speak English. Or to undertand someone elses
  169. naming convention.
  170. >
  171. >If you use public variables, then you are promising more than you need to -
  172. >using get/set avoids this.
  173.  
  174.     Usually you are right. I would not think public variables
  175. should be used often. More often than set/get functions,
  176. which IMHO are used by people whoe THINK that doing this
  177. makes the program object oriented and wonderful.
  178.  
  179. >
  180. >Using a public variable prevents both benign and malevolent changes to the
  181. >semantics, so there is, as you say, a tradeoff here. However attempting to
  182. >prevent malevolent changes in the class implementation seems pointless
  183. >to me: no matter what you do, the class implementor can always screw you
  184. >right royally, so when it comes to the crunch, you have to trust them.
  185.  
  186.     No, you don NOT have to trust them. C++ ensures type safe
  187. arguments to functions, FORTRAN did not.
  188.  
  189.     In C++ if your change is significant enough to warrant
  190. an change in interface (or indeed in the private interface)
  191. then it is guarranteed (with a make system) to recompile
  192. all code and check again for compatibility.
  193.  
  194.     In Eiffel, if a base class has an invariant, then all the
  195. derived classes must obey it too. And this can be tested
  196. at run-time. In C++ it is a matter of trust, but not in Eiffel.
  197. (Of course that is not all of semantics)
  198.  
  199.     And one wants to protect against ALL changes in semantics:
  200. not against making the change, but against making the change without
  201. informing ALL the users of the class.
  202.  
  203. >
  204. >No matter whether you use a public data member or get/set functions,
  205. >you will never be able to provide any useful guarantee of any sort about the
  206. >semantics of any class.
  207.  
  208.     Oh bull:
  209.  
  210.     class M2x2 { public: float a11, a12, a21, a22;}
  211.  
  212. The guarrantee is that I can have any 2x2 matrix. You CANT stop
  213. me, EVEN in a derived class.
  214.  
  215. >
  216. >If you assume that the class writer is of evil intent, then he/she can do
  217. >
  218. >class Matrix {
  219. >    ...
  220. >public:
  221. >    Matrix::Matrix(...) { abort(); }    // Ha, ha, ha! Beat that!
  222. >    ...
  223. >};
  224.  
  225.     class MyMatric : public Matrix {
  226.     public:
  227.         MyMatrix(){ // real constructor }
  228.     };    
  229. >
  230. >So what it comes down to is that the users of a class *have* to trust the 
  231. >class implementor to some degree. 
  232.  
  233.     Yes. But as little as possible!
  234.  
  235.     Why? Well, the class implementor is usually ME. I want the
  236. COMPILER to as much of the work as possible.
  237.  
  238. >Using public variables buys you very
  239. >little.
  240.  
  241.     Agreed. It is only a small issue.
  242.  
  243.     But small issues demonstrate poor thinking and that leads
  244. to flawed designs.
  245.  
  246.     If you want an example, have a look at the original
  247. Borland Object classes. They use get and set all over the
  248. place, they did about everything wrong you possible could
  249. in C++. Why? Because they were inspired by Smalltalk classes.
  250. And Smalltalk is a totally different language.
  251. >
  252. >As for reasons why you might want to change get/set for a matrix class,
  253. >even though matrices are objects with a very precise mathematical semantics,
  254. >there are many:
  255. >    - efficiency: sparse arrays, determinant caching, representing
  256. >              diagonal matrices efficiently, etc.
  257.  
  258.     Yes. I already agreed with efficiency as a reason.
  259. >
  260. >    - storing matrices on disk instead of in memory (if you don't have
  261. >      enough memory, then this is more than an efficiency issue)
  262. >      (although this one is cheating a little bit :-)
  263.  
  264.     No, acceptable reason.
  265. >
  266. >    And now without cheating:
  267. >    - array bounds checking 
  268.  
  269.     Well, thats cheating a bit: you should use an instance
  270. of a proper array class I suppose.
  271.  
  272. >    - ensuring that uninitialized elements are not referenced
  273.  
  274.     Yes, but you might also initialise them so the case
  275. never arises.
  276.  
  277. >    - in derived class OnScreenMatrix, display the new value of the matrix
  278. >      elements on screen whenever they are changed
  279. >    - etc.
  280.  
  281.     Sure. Here you would write a 'set' function. (No get function
  282. is needed though). But it would not be enough: what if I use
  283. an assignment??
  284.  
  285.  
  286. -- 
  287. ;----------------------------------------------------------------------
  288.         JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
  289.     Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
  290. ;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
  291.  
  292.