Prev: Lost in translation (with SPARK user rules)
Next: Sockets package in SPARK (Was: Lost in translation (with SPARK user rules))
From: Alex R. Mosteo on 2 Jun 2010 07:08 Luis Espinal wrote: > In article <hto4st$7g2$1(a)news.eternal-september.org>, Alex R. Mosteo > says... >> >>Luis Espinal wrote: >> >>>(...) >>> We have also come to learn that interfaces, the prohibition of multiple >>> inheritance, (...) were not a good idea at all. >> >>Thanks for the elaborate reply. Not expert in Scala/Java so I can't >>comment about most of it. >> >>However, seeing that Ada has just copied Java interfaces, I'd like to >>known a bit more in detail why you say what I quoted, if you have the >>time. I have used interfaces a bit and indeed have some grudges with them, >>but I'd like to know if the situation is worse than I think -- or perhaps >>I'm not using them 100% properly. >> >>Thanks in advance, >> >>Alex. > > Hi Alex - sorry I didn't reply sooner. I've been on the grind at work in > the last couple of days. > > The issue with interfaces (which is not universally accepted among Java > developers) is that they cannot be changed without incurring in changes to > classes implementing that interface. This is a big issue for the way in > which code is developed in Java. Let me try to illustrate: Hi Luis, thanks for the detailed reply. I understand your points clearly. My days of Java are a bit behind so I'm not sure what I'm about to say can be done in Java. In Ada, one could extend an interface adding a new method like this: procedure Moo (This : A) is null; And effectively it won't break any client, since it provides a default "no- op" implementation. It won't work for functions, obviously. In any case, clients would need to recompile, since in Ada land we're not talking of a world of JVMs and dynamic hot-plugging, I presume. This alone (the use of stand-alone executables) may make the problem much less of an issue. Also, not needing to specify defaults to overload a method could be of help? procedure Foo (This : A) is abstract; -- Added in 1st spec procedure Foo (This : A; Bar : A'Class) is null; -- Added in 2nd spec I've done sometimes the thing of having a insulating base class providing some/most of the interface core functionality, but at the same time I realized that this defeats to some degree the point of interfaces, since you can't inherit from two such base classes. In any case I feel your pain about the lot of Java programmers and frameworks ;-) I guess it has its goods and its bads. Alex. > > The common practice in Java is find a platform or framework (some sort of > high-level "virtual" OS for lack of a better word.) Then, either write > your apps on it, or develop another platform on top of it (another, more > refined, more business-specific "virtual" OS. So pretty much we (try to) > gradually refine the architecture of an application via an architecture > pre-defined by the runtime below it. Examples of this are JEE, Spring and > the Eclipse framework (and all the stuff + the kitchen sink that we throw > on top of them.) > > All those layers are typically defined with interfaces (since we don't get > multiple inheritance or mixin/traits). We end up with these long class > hierarchies, and lots and lots of artifacts implementing lots and lots of > interfaces. Libraries and libraries, and platforms and platforms... > without a concept of versions. > > So for example, you have an interface named A that defines a method foo(): > > public interface A { public void foo(); } > > And then you have a large number of classes implementing A, which are > distributed to 3rd parties. A while later, you find you must include a new > method on interface A: > > public interface A { public void moo(); } > > The moment you do that, you render every library that depended on old A > unusable. Either your clients won't be able to compile it, or if they will > get nasty run-time errors. The JVM will even refuse to load the old > classes because they do not conform with the new interface anymore. > > The folks in the eclipse framework, for example, have had to deal with > this problem by implementing "versioned" interfaces and have code deal > with them at run-time: > > public interface A { public void foo(); } > public interface A_1 { public void moo(); } > > class clientOfA { > void dooFooAndMaybeMoo( A someA ) > { > ... > if( someA instanceof A_1 ) > { > ((A_1)someA).moo(); > } > ... > } > > This could get out of hand (specially with sloppy programmers which, in > Java, unfortunately we have too many.) This can also be a concern with > people that develop frameworks and libraries for both external and > internal use. So what we do is that, in addition to implementing an > interface, we typically extend a an abstract base class that can insulate > us from possible changes to the interface: > > public interface A {...} > public abstract class AbstractA implements A {...} > public class ConcreteA extends AbstractA {...} > > If we need to change A, we simply change AbstractA so that clients of A > that extend AbstractA don't get forced to change their source... but that > doesn't do anything for those that still extend A directly. And having an > abstract base class like that defeats the purpose of being able of > creating arbitrary implementations of an interface. > > Other folks deal with that problem by creating Adapters... ending up with > a soup of design patterns going wild. > > Some people still think this is still a better trade-off over C++ styled > multiple inheritance because of the dreaded "diamond" problem. To me (and > this is strictly a personal opinion), it isn't. > > That's a lot of manual shamanism that should be better dealt with > syntactically. We should have had multiple implementation inheritance from > the get-go and just deal with it using the tools of the language and > careful planning. > > I think the Scala guys had the most wonderful of ideas by implementing > Traits. They offer many of the benefits of interfaces while simplifying > the ability of inheriting multiple implementations. The focus is no longer > on building behavior not just with inheritance but also with composition. > I don't need to worry if my object is a-something to that can do a-task; I > just have to worry that it can perform the task. > > I do think that interfaces have been great for specifying contracts. They > enforce an order on things. However, it is important to plan ahead > regarding interface versions. I don't know if this is a big deal in > Ada-land, but in the JVM-land, it has been. > > Please take it with a grain of salt. It is simply my observation, and with > software YMMV from one context to another :) > > - Luis Espinal (luis.espinal(a)gmail.com)
From: Yannick Duchêne (Hibou57) on 2 Jun 2010 09:09 Le Tue, 01 Jun 2010 23:30:54 +0200, Luis Espinal <Luis_member(a)newsguy.com> a écrit: > The common practice in Java is find a platform or framework (some sort of > high-level "virtual" OS for lack of a better word.) Then, either write > your apps > on it, or develop another platform on top of it (another, more refined, > more > business-specific "virtual" OS. So pretty much we (try to) gradually > refine the > architecture of an application Is it one of the reason why Java is virtual machine based ? is it related to this process or not ? -- There is even better than a pragma Assert: a SPARK --# check. --# check C and WhoKnowWhat and YouKnowWho; --# assert Ada; -- i.e. forget about previous premises which leads to conclusion -- and start with new conclusion as premise.
From: Colin Paul Gloster on 3 Jun 2010 12:54 On Wed, 26 May 2010, Peter C. Chapin sent: |-----------------------------------------------------------------------------| |"[..] | | | |[..] | |[..] Not surprisingly the Scala community, | |as evidenced by the posts on a Scala newsgroup, regard conciseness as an | |important feature for a programming language. I agree that conciseness can in| |some cases improve readability. However, I also believe that it can obscure a| |lot of important detail and make it hard to understand the execution cost of | |the code. [..]" | |-----------------------------------------------------------------------------| Passing a parameter to an Ada subprogram can look like choosing an element of an Ada array, with a very different execution cost. |-----------------------------------------------------------------------------| |"[..] | | | |However, the argument that I see some people putting forth on the Scala group| |is that conciseness is good because it saves typing. I really can't | |understand that. How hard is it to type? | | | |[..]" | |-----------------------------------------------------------------------------| Not very.
From: Yannick Duchêne (Hibou57) on 3 Jun 2010 12:09 Le Thu, 03 Jun 2010 18:54:57 +0200, Colin Paul Gloster <Colin_Paul_Gloster(a)acm.org> a écrit: Box design: (c) Peter C. Chapin. +---------------------------------------------------------+ | " Passing a parameter to an Ada subprogram can look | | like choosing an element of an Ada array, with a very | | different execution cost. " | +---------------------------------------------------------+ That's another area and not part of language semantic (readability refers to meaning, semantic). And you will nor see difference of execution cost between two different functions. -- There is even better than a pragma Assert: a SPARK --# check. --# check C and WhoKnowWhat and YouKnowWho; --# assert Ada; -- i.e. forget about previous premises which leads to conclusion -- and start with new conclusion as premise.
From: Yannick Duchêne (Hibou57) on 3 Jun 2010 12:11
Le Thu, 03 Jun 2010 18:09:38 +0200, Yannick Duchêne (Hibou57) <yannick_duchene(a)yahoo.fr> a écrit: > Box design: (c) Colin Paul Gloster. (was confused with names) -- There is even better than a pragma Assert: a SPARK --# check. --# check C and WhoKnowWhat and YouKnowWho; --# assert Ada; -- i.e. forget about previous premises which leads to conclusion -- and start with new conclusion as premise. |