From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,c08a7609345f4e5 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news4.google.com!feeder.news-service.com!feeder3.cambriumusenet.nl!feed.tweaknews.nl!138.195.8.3.MISMATCH!news.ecp.fr!news.jacob-sparre.dk!pnx.dk!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: Limited use for limited with? Date: Tue, 12 Oct 2010 21:09:29 -0500 Organization: Jacob Sparre Andersen Message-ID: References: <853314bc-0f79-435f-86a5-d7bcdd610731@c10g2000yqh.googlegroups.com> <36e886fa-b272-461f-bf86-a6b18366b64f@i5g2000yqe.googlegroups.com> <1eug9v5h5mf8d$.ud00hrz48lyr.dlg@40tude.net> <67044906-dacc-4526-b3f6-27e5323ab8fc@n3g2000yqb.googlegroups.com> <12chb4kbqt9ln$.zumsv1z9hqvk$.dlg@40tude.net> <292dd0bd-1fc4-4715-bb70-7655d0dc04eb@j24g2000yqa.googlegroups.com> <09c36bd6-edfa-42bf-8f33-e91b0a9b0737@26g2000yqv.googlegroups.com> <1f38791b-a579-49ed-839c-e6ff3867de76@30g2000yqm.googlegroups.com> NNTP-Posting-Host: static-69-95-181-76.mad.choiceone.net X-Trace: munin.nbi.dk 1286935772 2049 69.95.181.76 (13 Oct 2010 02:09:32 GMT) X-Complaints-To: news@jacob-sparre.dk NNTP-Posting-Date: Wed, 13 Oct 2010 02:09:32 +0000 (UTC) X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 6.00.2900.5931 X-RFC2646: Format=Flowed; Original X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.5931 Xref: g2news1.google.com comp.lang.ada:14499 Date: 2010-10-12T21:09:29-05:00 List-Id: "Maciej Sobczak" wrote in message news:1f38791b-a579-49ed-839c-e6ff3867de76@30g2000yqm.googlegroups.com... On 11 Paz, 08:23, "Randy Brukardt" wrote: >> > There are three options: >> >> >1. index/registry contains the actual objects - this has a big impact >> >on how the objects are created; this might impose limitations that >> >users will not want to accept > >> In our case, we did this, because we needed the capability to make the >> object database persistent. > >This is not my goal and there is no such requirement in my system, so >I don't consider it a reason for not using access types. Persistence is a very common requirement, so for general facilities it *is* a reason to avoid access types. ... >> IMHO, Interfaces are worthless. > >I hope you understand that this is a very strong statement. It >basically stands in direct opposition to the work that has been done >to introduce them into the language. I DID a lot of that work. It isn't the only work that I've done on the language that I didn't think was worthwhile (don't get me started on coextensions). But there are a lot of people that would disagree with me on interfaces; we added it for them, not for me! In every instance that I have ever wanted to use an abstract type, I have wanted to provide some data and or default implementations with that abstract type. The classic example is controlled types (where the private data of the root types provide the links used to manage the finalization), but that has happened in several places in Claw as well. Having to implement the same operation in the same way in almost every extension of an interface is not likely to add anything to maintainability nor to readability. So what "ility" is it adding?? Classwide routines are great for doing operations that are always handled the same way. But if the operation is *usually* done one way but in some circumstances needs to be done differently, overriding is needed and the inability to have concrete operations requires lots of manual repetition. In addition, hardly anything is common enough to really benefit from interfaces. Every hierarchy that I have dealt with is very shallow, with only a handful of levels of derivation. There isn't that many operations that are shared between object types. >> The contortions >> that we've gone through trying to use them for the queue containers > >There is no obligation to use them where they are not adequate. >However, this says absolutely nothing about their use in those places >where they *are* useful. The queue containers are about the most useful item that I could actually imagine for interfaces. This is a case with multiple plasible implementations and a well-defined set of operations that work with each implementation unmodified. If it doesn't work well on the queues, I'm skeptical that it can work well anywhere. ... >> If you use a single interface, you break type safety with accessing >> the data > >No, not at all. The type safety is not compromised in any way. >Consider: > > procedure Handle_Event (H : Handler_Access; Data : in Integer); > >(where type Handler_Access is access all Handler'Class) > >In what way is the type safety of Data compromised here? It's not. But it is highly unlikely that different events need the same data. So you have to have separate event handlers for each event. Once you have done that, there no longer is a common mechanism for registering/triggering events -- you have to recode it separately for each event. If that's the case, the concerns about coupling are pretty much eliminated, as both the object and the event have to know about each other anyway. >> In every instance where I've had to do some sort of event handling, I've >> written a separate specification for each handler. > >That's OK. These are defined as interfaces in my system. And how does this help? You can't make a call to some routine with an unknown parameter list, just because it is defined in an interface. So you still end up with a separate call to each handler, and all the interface has bought you is additional complication and lots of runtime overhead. ... >> But you are losing safety: both type safety and program safety (because >> of the dangling pointer issues) by doing so. > >Type safety is not compromised. All operations are strongly types. >Some of them might be lately bound (dispatching), but all are strongly >typed. If you think otherwise, please explain. You and I must be thinking of different solutions, because I can't see any way for that to work with a single handler registry type. And if you have multiple such types, I don't see why you'd want to introduce the complication: just deliver the events directly to the appropriate objects. >Program safety is not compromised due to the fact that all reasonable >use cases guarantee that handlers outlive the registries. Again, you are saying that no one that will program your system will make a mistake. It must be nice to have such perfect programmers -- I'd like to meet one someday. ;-) Work on the Ada standard and on Ada compilers has repeately reminded me that even if some use is an obvious pathology, it is pretty common that someone will try to use it. And it's not unusual that they've found a plasible use for it. (Programmers as a group are more clever than language designers or compiler writers, even if the latter individuals are brilliant.) So I always want to prevent misuse up-front, by the design if possible or by compile-time rules checks. >> Every solution has tradeoffs, >> and you are picking the one that has the worst attributes from an Ada >> perspective > >I'm still waiting for you to show it. And I still don't see it. Ada is all about tasking and about nested items. You are adopting a solution that will work poorly for both. And I've show the problems repeatedly. You don't believe they are problems because you are certain that no one will every try to use your code differently that you intended. In the unlikely case that you are right, I agree with you: any old design will work well -- use any spaggetti code that you want and it would *still* work. But I don't think you are being realistic: for instance, I want to avoid allocating objects when possible, because there are a lot less memory leaks when you let the compiler do the cleanup. So I declare a lot of objects in subprograms and in blocks. That doesn't mean that I wouldn't need one of them to handle an event! Anyway, I think we have to agree to disagree on this one, because we don't even have the same worldview. ... >> In the Web Server and Spam Filter, the events come from TCP/IP. In this >> case, we don't want a callback per-se because we want to treat each event >> as >> a "job", and schedule each "job" to be run by one of a pool of tasks. > >Yes, this is a possible approach, but tasks and jobs are bound in the >1:N way (that is, each job is delivered to exactly one task). Basic >multitasking patterns involving queues or other buffers are OK for this. > >But it is not applicable in general. Think about how messed up it >would become for N:M case (each job delivered to potentially many >tasks). N:M would be what I called chaos at the start of this thread! There has to be some structure to the events or you really do have chaos. So you have to partition that into a set of events that all go to a single object/task, and broadcast events that each go to a set of objects/tasks. That is, the program is a bunch of 1:N and N:1 events, and they don't (directly) interact. >It is true that in my system it *would* be possible to do this, but I >have chosen not to do it in order to avoid forcing the user (client >for you) to create additional tasks on his side. It is perfectly >possible to run the whole system in a single-tasking environment - >that is, the one that does not even support multiple tasks. Since my >system is targeted at embedded installations (among others), I >consider this to be an important feature. The user/client can always >add tasking if needed. It's too late at that point, as you now have a single event handler task as a bottleneck. If you need tasks, you have to add them early to get even a semblance of parallel execution. Even so, I understand your concern. Not all systems can use tasking effectively (although this is something that is changing rapidly, multicore chips are becoming the norm). I think it is necessary to use different patterns in the two cases ("jobs" vs. "events"), and I don't think it is a good idea to try to unify them. >> I don't think that there is a general pattern that is acceptable. > >I agree. But we are now discussing something different: you seem to >state that *some* pattern is *universally UNacceptable*, no matter >what - and this is something I don't agree with. There is nothing that is ever that black-and-white. This is a pattern that I think is best avoided if possible. But it clearly isn't always possible to avoid it. Registration is, for instance, the best way to build an object factory in Ada. But it is interesting that you're usually not storing pointers into the registration map in that case. Randy.