Re: [Edu-sig] Design Patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Scott David Daniels > > If I am not violating the Uniform Access Principal how do we express on > what > > basis I am not? > > This to me has to do with the set of calls in your API. Yes but according to the Uniform Access Principle: "All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation." My API is designed exactly and explicitly to betray this. That *is* my API. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Scott David Daniels > My strongest reaction has > to do with your wish to deny me the ability to make another choice If that is a reference to my opinion about the visibility of the built-in property function, and its real world impact... if I thought my opinion had would likely have impact, I would likely think about it harder ;) Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
Arthur wrote: > I have a line segment - defined as the segment connecting 2 points. The > interface allows the points to be picked and moved. > > The line segment has a length. I choose line.getLength() as my API > Am I - in fact - violating the Uniform Access Principal. > If I am, am I violating good programming practice? OK, my take is no -- you are choosing an API. My strongest reaction has to do with your wish to deny me the ability to make another choice; API design is an art, not a science, and not engineering. The whole API is what you should evaluate. I am certain we cannot produce a set of rules that guarantee a good API, not can we provide rules to avoid a bad API. > If I am not violating the Uniform Access Principal how do we express on what > basis I am not? This to me has to do with the set of calls in your API. It is hard to say with a coordinates and length API, it is easier with something richer like triangles, rectangles, and polygons. The length of the sides of all of those things should show up the same way; either as attributes or method calls. Variations between polygons and triangles, for example, would make me think you are letting your implementation show through too much. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> -Original Message- > From: Kirby Urner [mailto:[EMAIL PROTECTED] > "Information hiding" means sparing me the details. In an open source > world, > I might be able to see those details if I really cared about them. In the > case of a private bank, fat chance. Yes, we are at the core of some considerable sensitivity in my (other) world. And yes, we are touching upon emotion and politics as well as API design. Pausch advocates exposing folks to a 3d API that spares the user the need to understand what "rotate" and "translate" means to everybody else in the known world working in 3d. I disagree, to say the least. There is not a theory adequate to settle our disagreement. We end up, as Laura says (I think), only able to make judgment calls as to what is and what is not appropriate as to what to expose and what not to expose, depending on what we are trying to accomplish. Judgment calls are to me a-theoretical. I think I understand the basic theory - and reserve to the right to do little more than take it under advisement. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> Separating these matters in an educational setting is more than > problematic. > > Art In an educational setting, I use analogies. Think of interacting with a waiter in a restaurant. Your expectation is you name the foods and drinks you want, and after a period of time, those items arrive at your table. Later still, you pay for it all plus leave a tip. That's the API. But in some restaurants, the waiter is proud to memorize your order, and writes nothing. In some, the order is written down, but punched into a computer and the bill comes as a machine-printed slip. In most restaurants, the food is prepared in a kitchen not visible to customers. In others, it's prepared right in front of you, behind a counter, while you watch. Customers come to restaurants fully expecting to use the waiter API. But they may have little insight into the nuts and bolts of how this API is wired up behind the scenes. Maybe the waiter is part time. Maybe the cook lives in Hoboken. These details, though real, are "hidden" from the customers (but may come out in conversation). Furthermore, the inner workings may change. A new computerized checkout device is installed. Waiters need to be retrained, but not customers. The API is the same. In my MVC example, the Viewer expected a 'shape' object to support a specific API: verts and edges needed to be available as attributes. class Vpyview(object): """ A viewer: view using VPython """ def display(self, shape): self._garbagecollect() self._showverts(shape.verts) self._showedges(shape.edges, shape.verts) time.sleep(.1) But my Model class (a Triangle) defined neither per se. The information was there, but the API was not in accordance with the Viewer's needs. Presumably this Viewer is used with other shapes (polyhedra even!) and we don't want to write exceptional code just around triangles -- that'd get messy in a hurry. My solution, in this case, was to subclass Triangle2 and supply the missing attributes in the subclass. In the case of edges, this was a static list, defined once and for all in the constructor. In the case of verts, I used a property, so that the Viewer could just ask for verts (not a callable) and so that a triangle could quickly figure coords (also a property) behind the scenes. The upshot: shape.verts, in the eyes of the viewer, is simply a dictionary of xyz tuples with vertex label keys. class Triangle2(BaseTriangle): """ Model """ ... @property def coords(self): return {'A':self._pA, 'B':self._pB, 'C':self._pC} def _reset(self): ... self._pA = (0.0, 0.0, 0.0) self._pB = (a , 0.0, 0.0) self._pC = ((a**2 + b**2 - c**2)/(2.0*a), math.sqrt((-a+b+c)*(a-b+c)*(a+b-c)*(a+b+c))/(2*a), 0.0) class TriAdapter(Triangle2): """ Make a triangle work like a Shape, i.e. add edges and verts attributes """ def __init__(self, a,b,c): Triangle2.__init__(self, a,b,c) self.edges = [('A','B'),('B','C'),('C','A')] @property def verts(self): return self.coords Why allow coords and verts to be properties? Because these triangles are themselves mutable and the vertices may change position, even if how they're connected (the edges) doesn't change. Could I have gotten by without properties? Sure, but the code wouldn't have any easier to read or understand, or use. I'd still need to recompute everything when an edge was resized. This seems a real world enough example to get the point across: an API is like a contract, and once it's engrained, you may want to write adapters rather than tear into working code. Adapters aren't the same as properties, but they're another piece of the theory/nomenclature, and their implementation may *include* using properties. Another real world example: you go to a foreign country and the electrical sockets are different. Your appliance would work, if only you could plug it in. Do we go out and buy wire cutters, strip off the plug and attach a new one? No, hardly. We go out and buy an adapter, or bring one with us (like I did to Gothenburg). OO has adapters too, and properties may be a part of that. OO is about objects and the analogies are with objects in reality. Do we have properties in reality? You go to a bank and withdraw cash from your ATM. You (not you personally, because you know better) may imagine banks have big vaults full of cash, but actually they've loaned out the deposits and carry rather little cash. They may need to borrow from a different bank to cover your withdrawal. Do you need to care? No. You just want the ATM API to work as usual. "Information hiding" means sparing me the details. In an open source world, I might be able to see those details if I really cared about them. In the case of a private bank, fat chance. "Information hiding"
Re: [Edu-sig] Design Patterns
> -Original Message- > From: Laura Creighton [mailto:[EMAIL PROTECTED] > > My guess is that you think that properties violate 'Explicit is better > than implicit.' Not exactly. More like I think that it encourages "theory", and I appreciate Python as a-a-theoretical. The counter argument is that Python is so a-theoretical as to not be opposed to the imposition, with it, of any theoretical approach a practitioner might find appropriate or want to explore. And properties fit in there somewhere. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> -Original Message- > From: Kirby Urner [mailto:[EMAIL PROTECTED] > > > Kirby seems comfortable in the Meyerist camp. > > > > I think you might be reading something too sinister into "information > hiding" and are therefore against it. I did put a ;) after my comment on information hiding - taking the opportunity to be a bit glib, and knowing it. But still to me, OOP theory is just that - theory. In certain domains, it may be the best we have - so we go with it. In other circumstances, every decision can be purposeful and specific to the problem at hand, and the actual and concrete can overrule the theoretical. It's a matter of knowing where one is in a specific circumstance, I guess. Separating these matters in an educational setting is more than problematic. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> -Original Message- > From: Laura Creighton [mailto:[EMAIL PROTECTED] > One nice thing about overwriting __getattr__ and __setattr__ is > that when you are done you have something that fairly shrieks > 'black magic here'. Properties look innocuous. Some people go quite > nuts with them, and use them whenever possible, as if there was > something wrong with simple assignment in the first place. Yes. Yes. And in that way can be a bit of a trap to those of us feeling our way. A trap I find I fell into a bit. Which = in essence - is why I thought a discussion of the subject pertinent. I have disagreed with an aspect of Python design, which in IMO consciously obscures functions and concepts related to the copying of objects. Guido seems to feel strongly that too much visibility here encourages overuse by novices. Maybe true. But I think the lesson inherent in "copy" is worth the risk. IMO, the degree of visibility of properties is a clearer case of this kind of issue. Less upside to it. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
In a message of Fri, 26 Aug 2005 18:24:33 EDT, Arthur writes: >And am hoping he is quite wrong in the assessment that "information hiding" >is a base requirement for information science. ;) He is quite correct, but 'hiddenness' is not an infinite human good, such as health. It is quite possible to hide too much. Whether 'having things work like magic' is a good thing or not is always a tricky judgement call. >Kirby seems comfortable in the Meyerist camp. > >But I feel my anti-Meyerist sentiments are somehow bound to my pro-Python >sentiments. So am having trouble with my Meyerist Python friend's stance >. > >Art My guess is that you think that properties violate 'Explicit is better than implicit.' In the example in http://www.python.org/2.2.3/descrintro.html#property where x is restricted to positive values. >>> a = C() >>> a.x = 10 >>> print a.x 10 >>> a.x = -10 >>> print a.x 0 # I think that Art thinks this is too much magic >>> a.setx(12) >>> print a.getx() 12 >>> One nice thing about overwriting __getattr__ and __setattr__ is that when you are done you have something that fairly shrieks 'black magic here'. Properties look innocuous. Some people go quite nuts with them, and use them whenever possible, as if there was something wrong with simple assignment in the first place. Worst of all, they are easy enough to use that all the would-be-Nannies in the world can trivially write code to prevent you doing what they think is unwise. This is most irritating when you are wiser -- or more imaginative than they are. This bit us the other day. Somebody naively thought that not allowing certain variables to be set to zero would be a swell way to avoid divide by zero errors. The problem is that the natural idiom used all over the codebase is: x = fast-way-to-solve-the-equation-works-most-of-the-time(**argv) if x is 0: # too bad x = do-it-the-hard-and-slow-way(**argv) He stuck his property in, and all over campus people started getting weird mysterious errors. People who tried to debug it and suddenly found out that _assignment_ 'wasn't working' concluded that '_Python_ was broken'. Their mental model of 'how computer languages work' doesn't include properties. Laura ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> Kirby seems comfortable in the Meyerist camp. > I think you might be reading something too sinister into "information hiding" and are therefore against it. The brutal real world truth is the client wants an API that works today, but will complain if it doesn't deliver tomorrow, even if specs shift in the mean time. A lot of programming arises from this dual use: freedom to use now, freedom to change it under the hood later. Properties help insert a layer between mutable programmer code and a slick API that clients like and want to keep using. It's a matter of keeping a favorite notation relatively static, thereby insulating users from messy inner details. That's *one* meaning of information hiding, and I think a benign one. My world assumes you have access to source code. Information hiding is relative to something. If you have no source code at all, then it's all hidden, and so what's the point of even talking about what's hidden or not? > But I feel my anti-Meyerist sentiments are somehow bound to my pro-Python > sentiments. So am having trouble with my Meyerist Python friend's stance. > > Art I think you're espousing an open source ethic, but maybe confuse the purpose of properties with something "information hiding" needn't mean. It could just mean a notational integrity that insulates programmers from other programmers. It's like wearing business suits or casual dress. We don't want to keep adjusting our eyeballs from one freakazoid API to another. Just give us a uniform integrated control panel please, and do your behind the scenes work behind the scenes (but let us peek if we get curious). Kirby ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Scott David Daniels > > This is close to what I meant. I dislike properties that don't behave > as if they were attributes. Not exactly sure what that means. Seems there is a lot to this topic. I get to the fact that there is a Uniform Access Principle - with some authority behind it. """ The Uniform Access Principle, as published in Bertrand Meyer's Object-Oriented Software Construction, states that "All services offered by a module should be available through a uniform notation, which does not betray whether they are implemented through storage or through computation." It is described further with "Although it may at first appear just to address a notational issue, the Uniform Access principle is in fact a design rule which influences many aspects of object-oriented design and the supporting notation. It follows from the Continuity criterion; you may also view it as a special case of Information Hiding." """ I guess I am intuitively anti-Meyerist. And am hoping he is quite wrong in the assessment that "information hiding" is a base requirement for information science. ;) Kirby seems comfortable in the Meyerist camp. But I feel my anti-Meyerist sentiments are somehow bound to my pro-Python sentiments. So am having trouble with my Meyerist Python friend's stance. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
Kirby Urner wrote: >>So I find that rejecting it as naïve is fundamentally unresponsive. >>Art > > However in this case I don't think your views were rejected as naïve. On > the contrary, your views permeated a sophisticated discussion of use cases, > and design patterns more generally (s'been a rich thread) plus Scott sort of > liked your using () to connote dynamism (I didn't). This is close to what I meant. I dislike properties that don't behave as if they were attributes. That is, I'd like two accesses to the same property of a particular object to return the same value until the object has been "changed," and I don't like read access to a property to be a "real" change. There are three exceptions I allow in my personal aesthetic: * debugging code: All's fair for this case. Properties are _golden_ for allowing tracking things into a lot of code without changing that code. * instrumentation: Measurements can be accumulated about behavior, but shouldn't interact with normal operation. * performance:Achieving the same results with different performance is often the whole point of systems programming style programming. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> -Original Message- > From: Kirby Urner [mailto:[EMAIL PROTECTED] > I *enjoy* your exotic other-worldliness. Other than what, I'm wondering ;) Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
Hi Andre -- If you scroll back, you'll see I was specifying a triangle object in which sides a,b,c were passed to a constructor, *and* could be respecified on the fly, thereby changing the triangle. A validator made sure the proposed triangle was legal (triangle inequality not violated). Other than that, just go ahead and respecify a,b,c at will: >>> ok = Triange(3,4,5) >>> ok # whatever __repr__ > >>> ok.b = 3 >>> ok > So it went from right to isosceles just there, thanks to rebinding of side b. However, *only* sides could be respecified in this way. That was the game. Think of it as an abcTriangle. This design has its limitations and shouldn't always be used. It's handy when that's what you want. Angles A,B,C and xyz coordinates pA, pB, pC turned out to be consequent read-only values, but I decided to make them work like attributes from the user's point of view. You could get them, but not set them (directly). Down the road, I might add scale(), rotate() and translate() methods. These would be callables and expect arguments -- except I've already implemented scale() a different way, using __mul__: >>> newok = ok * 3 >>> newok Kirby ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
Disclaimer: I haven't followed this thread as closely as I should. Picking up on a few words from the discussion (namely "triangle" and "properties"). When I think of a real life triangle, I can describe it in terms of various "properties", such as: the length of each of its three sides, its area, the three internal angles, its perimeter, etc. Of course, most of these properties are interdependent. If I want to refer to a triangle property using the "dot" notation, I want to write: triangle.area triangle.perimeter triangle.shortest_side triangle.longest_side etc. Now, imaging taking a program similar to "Paint" and drawing a triangle. Then change it somewhat (by flipping it, lengthening one side, etc). [Unlike "paint", our program keeps track of objects' nodes.] Suppose I am lengthening one side from 100 horizontal pixels to 120 horizontal pixels (looking at the status bar where such information is displayed). When I change one value, others may change too. When I change one value, I am first and foremost interested about that particular value ... I don't want to have to think of what other values ("properties") may need to change. --- Now, back to computer programming Python properties make it possible to think of all of an object's attribute on an equal footing (given an appropriate design for the class to which the object belong). Without properties, I have to distinguish between values that can be assigned directly and those that must be computed. Of course, a lot of work has to be done behind the scene to keep things consistent. Java's "recommended" way would be to use a set method for assignment and a get method for retrieval (with the same required work done behind the scene). I find Python's properties much more elegant (and simpler for the end user) than having a whole bunch of get_this() set_that() to use. André ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> So I don't feel as off topic or off base as perhaps I should. > > Apologies. > > Art I don't feel you've been off topic or off base at all in this thread (nor really that much in general). The considerations you have about properties were worth raising. My point is I don't think your contribution was dismissed. On the contrary, use cases were presented, e.g. a Triangle with an attributes-only API. You've said since that you'd prefer a subtle namespace in which callables denote "on the fly" computing, whereas non-callables suggest more static or basic attributes of Triangles. That's all fine and good, but notice we're not dismissing your proposal by calling it naïve, let alone off topic. No, in my case, I've given thought to your preferences, as I would to those of a peer professional, and then thought "but I like properties and will continue using them, plus encourage my students to consider using them in their own code." That's where I came out. Different place. And so it is among professional programmers. It's clear to me that you and I have very different world views. That makes our discussions more interesting. I *enjoy* your exotic other-worldliness. Makes mine more palatable as well. :-D Kirby ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> So I find that rejecting it as naïve is fundamentally unresponsive. > > Art > However in this case I don't think your views were rejected as naïve. On the contrary, your views permeated a sophisticated discussion of use cases, and design patterns more generally (s'been a rich thread) plus Scott sort of liked your using () to connote dynamism (I didn't). The tone was always peer to peer. And we came out in different places re properties, which is fine. I'm not going to change my ways just because of peer group considerations -- I'm not that feckless. Kirby ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> -Original Message- > From: Arthur [mailto:[EMAIL PROTECTED] > > So I find that rejecting it as naïve is fundamentally unresponsive. Just to add - I would feel my approach - no question - more misplaced most other places. But think Guido's ability to retain a sense of naivety in the midst of the highly technical underpinning of his task is largely what makes Python what it is. So I don't feel as off topic or off base as perhaps I should. Apologies. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> From: Kirby Urner [mailto:[EMAIL PROTECTED] > You're welcome to your opinions. Sometimes you whine when it seems your > opinions are taken for what they're worth though, which *sometimes* (not > all > the time) ain't much in my book. We are in agreement. That is precisely when I whine. But there are times, in my view, where a naïve view is quite worthy of expression, provided it is recognized as such. I believe I both recognize when I am presenting a naïve view, and when such a view is worthy of expression. So I find that rejecting it as naïve is fundamentally unresponsive. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design Patterns
> >I think use cases were described, and demonstrated, in which the property > >feature made sense, e.g. we wanted an attributes-based API into our > >triangle object, but sometimes the results were computed on the fly. > > And I notice that without the use of properties, that which is computed on > the fly is identified as such. So that properties allow us to have an API > that which is unrevealing on this matter. I am not excited yet. Yes, you weren't excited by some other software engineer's design. But that's different from not seeing a use case (one would hope). I don't want my user to care what's "on the fly" in my triangle. I want to use attributes for all read-only properties. Simple and to the point. Adding () here and not there just clutters the space with irrelevant detail. I'll tell my user to look at the source code if said user cares that much about what's "on the fly." > Yes, I think I understand. *With* properties we can change our mind after > our API is set in stone and nobody will notice or need to adjust. > That was another use case, not identical to the first (i.e. the case of just wanting to use attributes, which could easily have been based on properties right from the start, i.e. there need be no after thoughts). > So that properties and their use case encourage us to release less > revealing API's all the time, to cover ourselves in the event we set > our API in stone prematurely. > They help us craft less cluttered and stupid APIs yes. Your idea to have () every so often, because it's on the fly -- I don't want that. My triangle is not that dumb 'n ugly, sorry (Python supports more than one aesthetic). > I don't like properties. > I do. > And certainly no more so from what I have learned from this attempt at > getting more clarity about them. > > And like to think my naivety on this kind of matter is a purposeful > naivety. > > Art You're welcome to your opinions. Sometimes you whine when it seems your opinions are taken for what they're worth though, which *sometimes* (not all the time) ain't much in my book. Kirby ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> Here's some code, which as yet doesn't actually make use of VPython -- but > that's where it's going. > And here's where it (the code) went. Very minimal, at this point but enough to get VPython actually doing something with the triangle. A student could start with this code and start adding stuff e.g. make it more colorful, add defaults (e.g. radius), cycle through random triangles in main() -- using a try loop to catch illegals -- and so on. Kirby === class Vpyview(object): """ A viewer: view using VPython """ def __init__(self): self._garbage = [] def display(self, shape): self._garbagecollect() self._showverts(shape.verts) self._showedges(shape.edges, shape.verts) time.sleep(.1) def _garbagecollect(self): for g in self._garbage: g.visible = 0 def _showedges(self, edges, verts): for e in edges: v0 = vector(verts[e[0]]) v1 = vector(verts[e[1]]) edge = cylinder(pos=v0, axis=v1-v0, radius = 0.1) self._garbage.append(edge) def _showverts(self, verts): for v in verts: v0 = vector(verts[v]) sph = sphere(pos=v0, radius=0.1) self._garbage.append(sph) from visual import * import time def main(): """ Main call sequence """ thescene = display(title='MVC Demo', center=(0,0,0), background=(.5, .5, .5)) thescene.autoscale = 0 theviewer = Vpyview() theshape = TriAdapter(3,3,3) pulser = Pulser(theshape, theviewer) pulser.run() ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> I might be a dead horse who is dead wrong, but the issue about how > properties fit into Python is certainly not straightforward in the least, > and responding as if it were is grossly unfair - to the question raised. > > Art I think use cases were described, and demonstrated, in which the property feature made sense, e.g. we wanted an attributes-based API into our triangle object, but sometimes the results were computed on the fly. Martelli shows this same use case with a rectangle object (Python in a Nutshell, pg. 85). As for using decorator syntax to define properties, Scott has shown how this might be done. However, this approach is entirely optional. Python coders may flag private attributes and methods with _ and __, with the latter causing name mangling based on class name: >>> class Foo(object): def __hidden(self): pass >>> dir(Foo) ['_Foo__hidden'...] Kirby ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:edu-sig- > [EMAIL PROTECTED] On Behalf Of Chuck Allison > Sent: Tuesday, August 23, 2005 6:19 PM > To: Kirby Urner > Cc: edu-sig@python.org > Subject: Re: [Edu-sig] Design patterns > > Hello Kirby, > > Thanks for this good input (you too, Scott). My syllabus is at > http://uvsc.freshsources.com/html/cns_439r.html. I like your point > about cutesy having its place. I just don't see a way to use what's in > HFDP as the basis for a programming assignment, but maybe it will come > after a few days. As a professor, I like having my ducks in a row a > priori, but that's not happening this first time around. Since I teach > 3 upper division courses, I'm just a little nervous about having time > to invent sufficient material. I was just hoping someone had had a > similar teaching experience I could "borrow" from. All comments > appreciated. Thanks again. Hi Chuck -- I don't have HFDP in front if me, but if it does MVC at all, I can imagine using the Triangle we've been discussing as a model, then adding viewer and controller objects, making the triangle change in some way (controlling it), while displaying (viewing it). Here's some code, which as yet doesn't actually make use of VPython -- but that's where it's going. Note that my viewer expects to work with a 'shape' object, which is supposed to have attributes verts (a dictionary of labeled vertices) and edges (a list of vertex pairs, using those labels). Since my triangle object wasn't written that way, I subclass a Triangle2 as TriAdapter, solely for the purpose of making it behave like a shape. Kirby === # uses code already/recently posted to this list for BaseTriangle class Triangle2(BaseTriangle): """ Model """ @property def coords(self): return {'A':self._pA, 'B':self._pB, 'C':self._pC} def _reset(self): a,b,c = self.a, self.b, self.c # for brevity self.perimeter = a + b + c s = 0.5 * self.perimeter self.area = math.sqrt(s * (s - a)*(s - b)*(s - c)) self.A = math.acos((-a**2 + b**2 + c**2)/(2.0*b*c)) self.B = math.acos(( a**2 - b**2 + c**2)/(2.0*a*c)) self.C = math.acos(( a**2 + b**2 - c**2)/(2.0*a*b)) self._pA = (0.0, 0.0, 0.0) self._pB = (a , 0.0, 0.0) self._pC = ((a**2 + b**2 - c**2)/(2.0*a), math.sqrt((-a+b+c)*(a-b+c)*(a+b-c)*(a+b+c))/(2*a), 0.0) def __mul__(self, scalar): a = self.a * scalar b = self.b * scalar c = self.c * scalar return self.__class__(a,b,c) __rmul__ = __mul__ class TriAdapter(Triangle2): """ Make a triangle work like a Shape, i.e. add edges and verts attributes """ def __init__(self, a,b,c): Triangle2.__init__(self, a,b,c) self.edges = [('A','B'),('B','C'),('C','A')] @property def verts(self): return self.coords class Pulser(object): """ A controller: makes a shape bigger in steps, then smaller, back to original """ def __init__(self, shape, viewer): self.shape = shape self.viewer = viewer def run(self): for i in range(15): self.viewer.display(self.shape) self.shape = self.shape * 1.1 for i in range(16): self.viewer.display(self.shape) self.shape = self.shape * (1/1.1) class Vpyview(object): """ A viewer: view using VPython -- very unfinished """ def display(self, shape): self._showverts(shape.verts) self._showedges(shape.edges) def _showedges(self, edges): # stub method for e in edges: print e def _showverts(self, verts): # stub method for v in verts: print v, verts[v] def main(): """ Main call sequence -- maybe loop through random triangles eventually """ theviewer = Vpyview() theshape = TriAdapter(3,3,3) pulser = Pulser(theshape, theviewer) pulser.run() ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Scott David Daniels > Arthur wrote: > > ... more to my point is the fact that I don't expect my programming > language > > to solve the problem of decoupling my API from my code. Because I don't > > expect it to be a solvable problem. > > I don't know if I'm beating a dead horse, but I don't claim properties > solves the problem of decoupling an API from its current implementation. > I do claim it provides another tool to express a properly decoupled > API. Yup. You're beating a dead horse. Everything I can find about properties in Java and C# relate it to encapsulation and data hiding. Everything I can find about Python relate that the language does not attempt to support encapsulation and data hiding in the Java and C# sense. I might be a dead horse who is dead wrong, but the issue about how properties fit into Python is certainly not straightforward in the least, and responding as if it were is grossly unfair - to the question raised. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Chuck Allison wrote: > My syllabus is at http://uvsc.freshsources.com/html/cns_439r.html. > One thing I've always wanted to see if the class is small enough: Groups shuffling other group's previous layers, and providing feedback (but not grades) to the original group. It is always a shock the first time you see someone else trying to use code you thought was clear. The reason for no grades is to eliminate the "grade race gaming" among groups. A good MVC exercise is a "fairy chess" (e.g. kriegspiel) server and clients. A sample sequence of constraints: (1) single game (2) single game with observers (3) game with observers w/o enough info to "cheat" by players. (4) multi-game server. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Arthur wrote: > ... more to my point is the fact that I don't expect my programming language > to solve the problem of decoupling my API from my code. Because I don't > expect it to be a solvable problem. I don't know if I'm beating a dead horse, but I don't claim properties solves the problem of decoupling an API from its current implementation. I do claim it provides another tool to express a properly decoupled API. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Hello Kirby, Thanks for this good input (you too, Scott). My syllabus is at http://uvsc.freshsources.com/html/cns_439r.html. I like your point about cutesy having its place. I just don't see a way to use what's in HFDP as the basis for a programming assignment, but maybe it will come after a few days. As a professor, I like having my ducks in a row a priori, but that's not happening this first time around. Since I teach 3 upper division courses, I'm just a little nervous about having time to invent sufficient material. I was just hoping someone had had a similar teaching experience I could "borrow" from. All comments appreciated. Thanks again. Tuesday, August 23, 2005, 5:29:33 PM, you wrote: >> -Original Message- >> From: Chuck Allison [mailto:[EMAIL PROTECTED] >> Sent: Monday, August 22, 2005 12:43 PM >> To: Kirby Urner >> Cc: 'Arthur'; 'Scott David Daniels'; edu-sig@python.org >> Subject: Re[2]: [Edu-sig] Design patterns >> >> Hello Kirby, >> >> Since this discussion has swerved a little, I'd like to pose a query. >> I've been using patterns since 1995 and am teaching a course starting >> Wednesday (a full semester course) on Design Patterns using the Heads >> First book. My query: do you have any ideas you might proffer for >> programming assignments? I'd like to give a handful of programming >> assignments throughout the semester that aren't as short and cutesy >> as what's in the book. Any ideas would be greatly appreciated! KU> Hi Chuck -- KU> You could throw out ideas for big projects that Python has gotten used for: KU> a) air traffic control and KU> b) languages training for the military KU> c) some other example only you know about (like El Fish) KU> (or are you teaching this as a Java class and just lurk with snake charmers KU> for ideas -- like I might do in a Ruby conference full of gem smiths). KU> In case 'a)' there's a backend database to consult, and a Tk canvas object KU> for showing airplanes along their vectors, converging/diverging from airport KU> termini. KU> In case 'b)', Python was glue around the game engine, knitting to a speech KU> recognizer that'd give feedback as to how a soldier/player was doing using KU> Arabic in Iraq (e.g. 'game over' if things were going badly -- like if a KU> cuss word was said). KU> I draw both of these examples from Pycon in March 2005, though I could have KU> chosen other examples from EuroPython or OSCON, also events on my calendar KU> this year. KU> Probably an important design pattern common to both of these applications is KU> MVC (model-view-controller). A key design pattern ideal is loose coupling KU> without losing coupling i.e. you want to stay connected, but you don't want KU> to overdo it, in case you want to recombine the various components down the KU> road. MVC would let us swap in a different database on the back, and only KU> have to teach the model about it, while the controllers and outputted views KU> would go against the same API and use the same markup (or whatever). KU> That being said, I think cutesy, short (even sexy) programs *are* what's KU> needed in an intro design patterns course, since it's the *patterns* that KU> matter, not industrial strength vertical market source code, crufted with KU> 10,001 years of specific knowledge domain content (like the stuff I do for KU> RHDS/MDRC -- clinical data around heart procedures, and tons more pattern KU> language where that came from (not being an MD, I never had to learn much of KU> it)). KU> But I haven't seen your syllabus and don't know where in the curriculum your KU> particular course fits in. I'm simply extrapolating from my own position, KU> and our circumstances may not match (e.g. you probably didn't spend most of KU> the day mixing wood stains and applying them to wood products -- like, KU> welcome to Oregon/SiliconForest). KU> Kirby KU> ___ KU> Edu-sig mailing list KU> Edu-sig@python.org KU> http://mail.python.org/mailman/listinfo/edu-sig -- Best regards, Chuck ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: Kirby Urner [mailto:[EMAIL PROTECTED] > They're not here to whine about not being mere "math notations" as if that > would be an improvement. That's one way to attempt to characterize my point - or Graham's point, for that matter. Except that it of course misses the point. And is a bit obnoxious. The usual. My target, if anything, is not Python - but the pressure on it to be more Java and C# like. But more to my point is the fact that I don't expect my programming language to solve the problem of decoupling my API from my code. Because I don't expect it to be a solvable problem. Seems to me to make more sense if my programming language provides the environment for deriving concrete solutions to defined problems. And project management tools (and human beings interacting with human beings) manage phase-in and change. Whatever. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> In his mind, (and I think in yours as well) computer languages are more > like mathematical notation than a form of technology. And as such, > evolution is slower - not at the pace of the changes in the underlying > technology. However I'm sometimes in the mood to not draw this line between notation and technology, looking at language as technology, as tools. And yes, different technologies evolve at different rates. Bucky kept saying the lead time from prototype to mainstream was a key variable, and in electronics might be about 3 years, whereas in housing it might be at least 10 if not more. So he figured housing prototypes in the 1940s might pan out in the 1960s, and to some extent they did (and didn't). Plus he kept making prototypes, as did his students (J. Baldwin and Joe Clinton come to mind). > > Though certainly not uninfluenced by those developments. The most > important technological development he seems to point to is the > increasing raw power and speed of processors, which allow languages > to design away from a preoccupation with performance issues. However it's also important that, given this opportunity for faster physical cycling, per the silicon chip computer, software engineers were able to rise to the occasion and give us VHLLs like Python, i.e. were able to take advantage of those extra fast cycles and yet still make the language parsable and machine friendly enough for a CPU (which is ultimately nothing more than a fast arithmetical/logical unit, no matter how fast it goes). > He thinks - though without great confidence in his intuition here - that > Java is an example of a language headed down a dead-end evolutionary path. > Than so must too be C#. > A language has a half life. Big expensive systems that aren't broken don't need to be replaced, only tinkered with, so you have this long aftermarket for language skills, even when the language itself is "officially" dead. FORTRAN is a good example. At the OSCON/Stonehenge party this year, Jeff Zucker (a Perl saint) and I met up with a FORTRAN guy who to this day works on optimizing FORTRAN compilers, to run more effectively against today's chips. Because lots of big fancy computer models still perform useful service and make heavy use of FORTRAN. > Despite having some understanding that it must be annoying to hear > high-fallutin theory from someone at my level in this domain, I persist. > > And it seems to me that the evolutionary successful language will include > in its approach clear and concise constraints on its ambitions. > So far you haven't said anything I disagree with. Just adding emphasis: software had to meet the integrated chip designers at least half way, and computer languages aim for a layer in a long term archeology that could include working bits for centuries, if not millennia -- just as centuries old math notation still expresses algorithms in useful form today (your original point). > If I am understanding "properties" mostly correctly, and in fact their > reason for being is to allow for a fundamental midstream redesign of a > program without alteration of that program's API, I am thinking something > to the effect that it is only possible to do the impossible in half- > measures, and half-measures are only half-measures and who wants to work > in an environment of half-measures. In Java, you should probably work out ahead of time if you want to use private variables cloaked in protective getters/setters, so that you might continue fiddling with the guts indefinitely, even as your users experience and enjoy a simple attributes-based API that hardly ever changes (like the front panel on a TV: channel and volume, yet no tubes inside (not even a picture tube these days)). In Python, you have more liberty to wrap what used to be a simple attribute in a property, and so maybe don't have to hard code so many design decisions up front. Java coders may be more likely to practice "defensive programming" than Python coders and make everything private and method-protected up front. This philosophy is manifest throughout the language (with its private, protected, and public attributes -- whereas in C++ you also have friends [1]). Some say Python is a "consenting adults" language, with permissions by convention vs. enforced by a nanny compiler (I'm not saying the latter can't be a nice experience also). > I don't think mathematical notation, for example, includes the concept of > the half-measure. > > Whatever. > > Art For me, non-executing math notation needn't be enshrined as the ideal. So much about math involves insulating one's self from having to deal with real world complexity (only to discover it later, one hopes in some manageable form). Computer languages ventured off into the wild west and took on whatever features we needed to do real time accommodation of client wishes. So I'm not nostalgic for the good old days, before we had computer science. I don't pine for a "math ru
Re: [Edu-sig] Design patterns
> -Original Message- > From: Chuck Allison [mailto:[EMAIL PROTECTED] > Sent: Monday, August 22, 2005 12:43 PM > To: Kirby Urner > Cc: 'Arthur'; 'Scott David Daniels'; edu-sig@python.org > Subject: Re[2]: [Edu-sig] Design patterns > > Hello Kirby, > > Since this discussion has swerved a little, I'd like to pose a query. > I've been using patterns since 1995 and am teaching a course starting > Wednesday (a full semester course) on Design Patterns using the Heads > First book. My query: do you have any ideas you might proffer for > programming assignments? I'd like to give a handful of programming > assignments throughout the semester that aren't as short and cutesy > as what's in the book. Any ideas would be greatly appreciated! Hi Chuck -- You could throw out ideas for big projects that Python has gotten used for: a) air traffic control and b) languages training for the military c) some other example only you know about (like El Fish) (or are you teaching this as a Java class and just lurk with snake charmers for ideas -- like I might do in a Ruby conference full of gem smiths). In case 'a)' there's a backend database to consult, and a Tk canvas object for showing airplanes along their vectors, converging/diverging from airport termini. In case 'b)', Python was glue around the game engine, knitting to a speech recognizer that'd give feedback as to how a soldier/player was doing using Arabic in Iraq (e.g. 'game over' if things were going badly -- like if a cuss word was said). I draw both of these examples from Pycon in March 2005, though I could have chosen other examples from EuroPython or OSCON, also events on my calendar this year. Probably an important design pattern common to both of these applications is MVC (model-view-controller). A key design pattern ideal is loose coupling without losing coupling i.e. you want to stay connected, but you don't want to overdo it, in case you want to recombine the various components down the road. MVC would let us swap in a different database on the back, and only have to teach the model about it, while the controllers and outputted views would go against the same API and use the same markup (or whatever). That being said, I think cutesy, short (even sexy) programs *are* what's needed in an intro design patterns course, since it's the *patterns* that matter, not industrial strength vertical market source code, crufted with 10,001 years of specific knowledge domain content (like the stuff I do for RHDS/MDRC -- clinical data around heart procedures, and tons more pattern language where that came from (not being an MD, I never had to learn much of it)). But I haven't seen your syllabus and don't know where in the curriculum your particular course fits in. I'm simply extrapolating from my own position, and our circumstances may not match (e.g. you probably didn't spend most of the day mixing wood stains and applying them to wood products -- like, welcome to Oregon/SiliconForest). Kirby ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
- Original Message - From: Scott David Daniels <[EMAIL PROTECTED]> > If I wait until I have actual users, I can get > real statistics on how the use the API. We decouple our work this > way. But in my look of it, properties are a "solution" to one of a nearly infinite set of these kinds of possibilites. And in that sense a half-measure. Certainly many areas will remain where our API and our design are irretrievably coupled. All I can try to do is offer the perspective of of a mid-brow developer, who tries. Again, in the case of the development of PyGeo - and willing to refactor until the cows come home - the solutions to problems seemed to be mostly a process of discovery. When I found a better way to do something than I had before, I knew it was better and I knew why it was better. And Python as a languagfe and as as disclipline seemed more than cooperative as a partner, and guide in the process. "Properties" being a rare distraction. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Chuck Allison wrote: > Since this discussion has swerved a little, I'd like to pose a query. > I've been using patterns since 1995 and am teaching a course starting > Wednesday (a full semester course) on Design Patterns using the Heads > First book. My query: do you have any ideas you might proffer for > programming assignments? I'd like to give a handful of programming > assignments throughout the semester that aren't as short and cutesy > as what's in the book. Any ideas would be greatly appreciated! What subject and to whom? If programming and/or CS, I'd be tempted to give a chain of assignments where the requirements swerve, showing the value of malleability in code design. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Arthur wrote: > If I am understanding "properties" mostly correctly, and in fact their > reason for being is to allow for a fundamental midstream redesign of a > program without alteration of that program's API, I am thinking something to > the effect that it is only possible to do the impossible in half-measures, > and half-measures are only half-measures and who wants to work in an > environment of half-measures. > > I don't think mathematical notation, for example, includes the concept of > the half-measure. OK, how about this explanation. If I am providing software support to a group of scientists running experiments, I can give them an API and the fastest-to-write code that passes tests. Once I've done that, they can get to work using the software while I go about the work of making the software more reasonably designed and responding to efficiency problems that they actually encounter. We use the API as a "treaty point" -- they stick to using it, and I stick to providing it. This structure can also be used to provide the "for free work-alike" and the "pricey efficient" versions. Properties allows me to determine later (perhaps after watching how they actually use the API) whether I should precalculate the triangle angles, recalculate them each time, or find an even fancier version where I compute them each the first time on demand and re-use those results, invalidating the angles whenever a side is changed. If I have to make those design decisions up front, I have to assume a pattern of use. If I wait until I have actual users, I can get real statistics on how the use the API. We decouple our work this way. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Hello Kirby, Since this discussion has swerved a little, I'd like to pose a query. I've been using patterns since 1995 and am teaching a course starting Wednesday (a full semester course) on Design Patterns using the Heads First book. My query: do you have any ideas you might proffer for programming assignments? I'd like to give a handful of programming assignments throughout the semester that aren't as short and cutesy as what's in the book. Any ideas would be greatly appreciated! Monday, August 22, 2005, 11:08:42 AM, you wrote: KU> There's a long history of coders seeking consensus, but not arriving at any KU> set in stone answers (no carved tablets at the Smithsonian), in part because KU> the backdrop is always shifting, in terms of languages and technologies. KU> The design patterns movement is the latest chapter in the series, drawing KU> inspiration from that 'pattern language' book beloved by the architects, and KU> followed by a big splash by the Gang of Four (an allusion to recent Chinese KU> political history). O'Reilly's 'Head First Design Patterns' is one of the KU> most pedagogically sophisticated in this tradition to date (I'm still KU> somewhat awed by it, though I've heard others express a wish for still KU> greater content density): KU> http://www.oreilly.com/catalog/hfdesignpat/ KU> We had the structured programming revolution, which tossed out the GOTOs, KU> and the object oriented revolution. Under the hood, we've been moving to KU> virtual machine platforms with their own byte code languages. This paradigm KU> has taken over at Microsoft and places (i.e. .NET). Python is one of these KU> VM languages, as are Java and C# (the latter being system languages, less KU> agile, yet very necessary, as implementation languages for Python itself KU> among other things). -- Best regards, Chuck ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> I guess. > > Though I can't say I find there to be much consensus out there about what > language features truly make for robust software development from group or > community efforts. There's a long history of coders seeking consensus, but not arriving at any set in stone answers (no carved tablets at the Smithsonian), in part because the backdrop is always shifting, in terms of languages and technologies. The design patterns movement is the latest chapter in the series, drawing inspiration from that 'pattern language' book beloved by the architects, and followed by a big splash by the Gang of Four (an allusion to recent Chinese political history). O'Reilly's 'Head First Design Patterns' is one of the most pedagogically sophisticated in this tradition to date (I'm still somewhat awed by it, though I've heard others express a wish for still greater content density): http://www.oreilly.com/catalog/hfdesignpat/ We had the structured programming revolution, which tossed out the GOTOs, and the object oriented revolution. Under the hood, we've been moving to virtual machine platforms with their own byte code languages. This paradigm has taken over at Microsoft and places (i.e. .NET). Python is one of these VM languages, as are Java and C# (the latter being system languages, less agile, yet very necessary, as implementation languages for Python itself among other things). > Python itself can be thought of as a robust community > effort - in C, which itself probably pre-dates/ignores much of the lessons > of what is necessary for such effort. Java seems obsessed with these kinds > of concerns - which is why I do in fact find coding in it as a solo as a > kind of foolishness. And now we have IronPython in C#. C is like clay -- it can be anything you want it to be if you're good at it, which Guido and friends are (I'm not -- I enter the picture as an xBase coder, working up the dBase II, III, IV, FoxPro fish ladder (we've always had an interactive 'dot prompt,' which is why Python's >>> seems so natural to us (there're other FoxPro geeks out there, bending a Python framework into a familiar shape (named Dabo), as I learned at Pycon in DC last March [1]))). The object orientation was always there in Python, but user-defined classes were originally 2nd class citizens. Getting them to be top level, unifying types and classes, has been a long haul saga within the Python community. I'm still a bit hazy myself on how to subclass some of the primitive types. Where do you store the value? I appreciated getting a history lesson on Python's origins and early evolution from Guido himself in Sweden, where he talked to a packed upper floor room full of mostly newbies (EuroPython had a friendly newbie track). > OTOH, I find code readability absolutely satisfying, even without an > expectation that anyone else will in fact be reading it. > > Whatever. > > Art I'm glad to hear it, as I do expect PyGeo code will be eyeballed by many more newbies as time goes on, ready to get their feet wet as strangers in a strange land. Your coding style will be an early influence on these little penguins. One of the challenges I had @ OSCON was how to talk about Elastic Interval Geometry (EIG) as inspired by Kenneth Snelson and others, without being off topic. Because the best open source EIG apps are written in Java (Springie and Fluidiom), and the best closed source offering (Alan's SpringDance) is in Delphi. My solution: write the presentation manager itself in Python, such that at any given moment, even if the slides were showing Java creations, the screen itself would be Python + Pygame driven (I also went out over the Internet to demo the Java applets live, but only for a few minutes). This strategy worked well IMO (plus I got positive feedback from people in the audience who came up to me during the rest of the conference). My code, though somewhat quirky (look at the weird way I pass parameters -- inside a parameters object), isn't especially crash prone, does what it's supposed to do.[2] I too am an influence, and fortunately just one of many (my stuff should be part of a balanced diet). Kirby [1] http://mybizmo.blogspot.com/2005/03/pycon-2005.html [2] http://www.4dsolutions.net/ocn/oscon2005.html ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: Kirby Urner [mailto:[EMAIL PROTECTED] > > A lot of these lessons about robust software development come from group > or > community efforts. Some aspects of Python maybe don't much excite you > because you're primarily a solo coder (as am I much of the time). I guess. Though I can't say I find there to be much consensus out there about what language features truly make for robust software development from group or community efforts. Python itself can be thought of as a robust community effort - in C, which itself probably pre-dates/ignores much of the lessons of what is necessary for such effort. Java seems obsessed with these kinds of concerns - which is why I do in fact find coding in it as a solo as a kind of foolishness. OTOH, I find code readability absolutely satisfying, even without an expectation that anyone else will in fact be reading it. Whatever. Art ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> Why do I find this unsatisfying? > I think part of the picture is you're coding for yourself i.e. your APIs are used internally by your own code. Refactoring *everything* is always a possibility. Suppose you'd already published a Triangle class API and then discovered you needed more dynamism. The property feature lets you sneak in some methods without changing the already-published API and breaking client code. A lot of these lessons about robust software development come from group or community efforts. Some aspects of Python maybe don't much excite you because you're primarily a solo coder (as am I much of the time). Kirby ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> Though when we add another dimension, all tetras are projectively > equivalent. Part of why I can't adjust to a focus on a tetra that happens > to be regular in some way. > > Art > Well, another way of putting it is: all tetrahedra are the same regular one, except not because of viewpoints. Kirby ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Arthur wrote: > > As an API matter, I find myself liking the clue that "()" provides as to > whether one is accessing something designed be determined dynamically. In general I agree with that sentiment. > I find myself leaning towards the option of making the use of properties go > away in PyGeo. If you want to keep anything as properties, I'd keep the ones those properties with the least dynamic nature. --Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: Kirby Urner [mailto:[EMAIL PROTECTED] > > Good point about all triangles being equivalent given projection. In > nailing down the angles, we've inadvertently defined a fourth vertex: the > point of view. Given we're talking four vertices, we should maybe rename > our class Tetrahedron ;-D. Good solution - as it leaves open the question as to where is the triangle and where is the point of view ;) Though when we add another dimension, all tetras are projectively equivalent. Part of why I can't adjust to a focus on a tetra that happens to be regular in some way. Art ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> PyGeo has a Triangle object, inherited from the Plane object. It exists > mostly for drawing purposes, as the portion of the plane enclosed by the > infinite lines connecting any 3 points. Since all Triangles are > projectively equivalent, in the context of PyGeo there is little to be > gained by saying much of anything about any particular triangle - and > little > is. > > > Art Good point about all triangles being equivalent given projection. In nailing down the angles, we've inadvertently defined a fourth vertex: the point of view. Given we're talking four vertices, we should maybe rename our class Tetrahedron ;-D. A transformation that has no impact on angles, is scaling. A feature I'd like to add to the Triangle sub/class is scalability -- using operator overloading why not? Here a design question is: should mytri * 3 change mytri, or should it return a new object. My preference is for the latter, since we can always rebind mytri to the output of __mul__. Should I also define __div__ while I'm at it? class Triangle2(BaseTriangle): def _reset(self): self.perimeter = self.a + self.b + self.c s = 0.5 * self.perimeter self.area = math.sqrt(s * (s - self.a) *(s - self.b) * (s - self.c)) self.A = math.acos((-self.a**2 + self.b**2 + self.c**2) / (2.0 * self.b * self.c)) self.B = math.acos((self.a**2 - self.b**2 + self.c**2) / (2.0 * self.a * self.c)) self.C = math.acos((self.a**2 + self.b**2 - self.c**2) / (2.0 * self.a * self.b)) def __mul__(self, scalar): a = self.a * scalar b = self.b * scalar c = self.c * scalar return Triangle2(a,b,c) __rmul__ = __mul__ >>> reload(trig) >>> from trig import Triangle2 as Tri >>> mytri = Tri(3,4,5) >>> mytri = mytri * 3 >>> mytri.area 54.0 >>> mytri.a 9 >>> math.degrees(mytri.C) 90.0 Other enhancements: I could add xyz coordinates as read-only, but have translation, rotation and scale methods (this last already defined) make them change. Having xyz coordinates will allow me to feed triangle objects to draw objects, e.g. for output to VPython, POV-Ray, VRML or what-have-we. Kirby ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: Kirby Urner [mailto:[EMAIL PROTECTED] > A weakness in the above design: we only check for violations of triangle > inequality in the constructor, yet allow changes to a,b,c through the API. Among my list of unsupportable theories is one to the effect that any attempt to build a truly OOP hierarchy of geometric objects requires one to get to geometric fundamentals and that requires one to get down to projective ideas. Apparently there is in OOP theory a nearly irresolvable paradox of the relation of the circle to an ellipse in a OOP hierarchy. But from a projective point of view they are only the same object, viewed from different perspectives, i.e. they are projectively equivalent. So attempting to distinguish them as different levels of some hierarchy is bound to be problematic. It's really a geometric problem disguised as a programming one. IOW, attempting to fit these objects into an OOP hierarchy chain can only be an attempt to fit a round ellipse into a square circle, or vice versa ;) PyGeo has a Triangle object, inherited from the Plane object. It exists mostly for drawing purposes, as the portion of the plane enclosed by the infinite lines connecting any 3 points. Since all Triangles are projectively equivalent, in the context of PyGeo there is little to be gained by saying much of anything about any particular triangle - and little is. Art ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Scott David Daniels > > I'd propose two reasons why properties are so successful. > > The first explanation comes from eXtreme Programming. One big goal of > XP is to stop wasting time doing "big design up front." Then my situation is a bit ironic. What I don't seem to have realized - at least to my own satisfaction - is some rational scheme for the use of properties. They are used - somewhere in the range from haphazardly to intuitively. So I am left to refactor working code to give some scheme to my use of properties. And since this refactoring is coming at a fairly late stage of design, I don't feel the same need to leave my XP options open to the extent that I might had I thought more thoroughly about the use of properties earlier in the process. So where I come out on the use of properties now might not be the same as where I would have come out at some different point. Why do I find this unsatisfying? As an API matter, I find myself liking the clue that "()" provides as to whether one is accessing something designed be determined dynamically. So I find myself leaning towards the option of making the use of properties go away in PyGeo. Art ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Scott: > def writeprop(viewvar): > '''decorator makes a property from access and a write method''' > def view(self): > return getattr(self, viewvar) > def buildprop(writemethod): > return property(view, writemethod) > return buildprop > Pretty fancy Scott and again, highly worthy of study. An element in this design pattern is using a function (writeprop) to build the decorator function (buildprop) that'll transform the following def (e.g. def c). Scott used the same technique when he enhanced my hypertoon program (a VPython cartoon generator) with decorator syntax. @f1(args) def f2: pass uses f1(args) to build a function which then takes f2 as its argument, rebinding the result to f2, i.e. f2 = (f1(args))(f2), where f1(args) by itself returns a callable. In this case, buildprop returns a curried property function (curried in that the 'view' method is already bound, defined in terms of getattr). The decorator returns a function the effect of which is equivalent to 'c = property(view, c)' i.e. c-the-function goes in as buildprop's writemethod and is rebound to make c a property. > @writeprop('_c') > def c(self, v): > self.check(v, self.a, self.b) > self._c = v > self._reset() Here's a similar base triangle class without the decorators: class BaseTriangle2(object): @classmethod def check(klass, a, b, c): '''Check three lengths for suitability as triangle sides''' if a >= b + c: raise ValueError, 'Too long: %s >= %s + %s' % (a, b, c) if a <= abs(b - c): raise ValueError, 'Too short: %s <= abs(%s - %s)' % (a, b,c) def __init__(self, a, b, c): self.check(a, b, c) self._a = a self._b = b self._c = c self._reset() def __repr__(self): return '%s(%s, %s, %s)' % (self.__class__.__name__, self.a, self.b, self.c) def _reset(self): '''Called whenever the sides of the triangle change''' pass def _seta(self, v): self.check(v, self.b, self.c) # fixed typo in original self._a = v self._reset() def _setb(self, v): self.check(v, self.a, self.c) self._b = v self._reset() def _setc(self, v): self.check(v, self.a, self.b) self._c = v self._reset() def _geta(self): return self._a def _getb(self): return self._b def _getc(self): return self._c a = property(_geta, _seta) b = property(_getb, _setb) c = property(_getc, _setc) Kirby ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Arthur wrote: >>What beyond sugar for leaving off a "()" when trying to retrieve a value >>from a method are we accomplishing by using properties? I have tended to >>look at properties mostly an accommodation to those coming from other >>languages which have something similar, but never as something that was >>core >>to Python or a Pythonic approach to things. Am I missing something >>fundamental? > > > The searching I do on this point only confirms to me that my own confusion > is well shared - perhaps indicating this to be an area not totally OT for > this forum. > > Ray Hettinger's "How-To Guide for Descriptors" > > http://users.rcn.com/python/download/Descriptor.htm > > covers properties, but the use case given is extremely unsatisfying - > essentially offering a situation where a fundamental design change has been > made to a program in mid-stream, and since properties were used in the > initial design, the change can be made with little refactoring. I'd propose two reasons why properties are so successful. The first explanation comes from eXtreme Programming. One big goal of XP is to stop wasting time doing "big design up front." I've spent enough time in companies where long design meetings (months) produced huge design documents. The documents themselves had a tendency to look like everything was nailed down, while not really answering a lot of questions that had to be solved when writing the code. The length of time spent producing the document, and the general unavailability of the group that wrote it (they typically moved into other committees to write other design documents), led to an increasingly rigid design that reflected neither discoveries or innovations from the coders nor changes in requirements (or at least our understanding of those requirements). XP can be seen as a reaction to that problem. The second explanation is much lower level. In O-O code, there is a distinction between interface and implementation. Essentially, the interface to an object is how the object behaves from a user of that object's point of view. The implementation is how that object accomplishes its behavior. When you separate these concerns, you can more likely keep a programs complexity (in the sense of debugging/ extending) from growing exponentially with the number of lines of code. Properties let you to hide the trade-off between accessing a stored value and computing it on the fly. Without properties, the interface to classes that want to reserve the access/calculate tradeoff must use the Java-like "getVar" functions to fetch any values that might be calculated. > What would it take to create a @property decorator that allows one > to set as well as get? Would we want to? def writeprop(viewvar): '''decorator makes a property from access and a write method''' def view(self): return getattr(self, viewvar) def buildprop(writemethod): return property(view, writemethod) return buildprop Triangle as an example: import math class BaseTriangle(object): @classmethod def check(klass, a, b, c): '''Check three lengths for suitability as triangle sides''' if a >= b + c: raise ValueError, 'Too long: %s >= %s + %s' % (a, b, c) if a <= abs(b - c): raise ValueError, 'Too short: %s <= abs(%s - %s)' % (a, b,c) def __init__(self, a, b, c): self.check(a, b, c) self._a = a self._b = b self._c = c self._reset() def __repr__(self): return '%s(%s, %s, %s)' % (self.__class__.__name__, self.a, self.b, self.c) def _reset(self): '''Called whenever the sides of the triangle change''' pass @writeprop('_a') def a(self, v): self.check(v, self.b + self.c) self._a = v self._reset() @writeprop('_b') def b(self, v): self.check(v, self.a, self.c) self._b = v self._reset() @writeprop('_c') def c(self, v): self.check(v, self.a, self.b) self._c = v self._reset() # One kind of triangle with angles: class Triangle(BaseTriangle): @property def perimeter(self): return self.a + self.b + self.c @property def area(self): "Heron's Formula" s = 0.5 * self.perimeter return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c)) @property def A(self): return math.acos((-self.a**2 + self.b**2 + self.c**2) / (2.0 * self.b * self.c)) @property def B(self): return math.acos((self.a**2 - self.b**2 + self.c**2) / (2.0 * self.a * self.c)) @property def C(self): return math.acos((self.a**2 + self.b**2 - self.c**2) / (2.0 * self.a * self.b)) # Another kind of triangle with angles: class Triangle2(BaseTriangle
Re: [Edu-sig] Design patterns
Hi Arthur -- Yes, decorator syntax isn't designed to integrate with properties quite the same way. All a decorator does is run the subsequently defined function f2 through the f1 in @f1, rebinding f2 to the returned output of f1. E.g. 'f2 = f1(f2)' and '@f1; def f2(): pass' amount to the same thing. The non-decorator version of Triangle, with properties, might be: >>> import math >>> class Triangle(object): def __init__(self, a,b,c): "Construct a triangle" if (c >= a + b) or (a >= b + c) or (b >= a + c): raise ValueError("Illegal edges: %s/%s/%s" % (a, b, c)) self.a = a self.b = b self.c = c def getArea(self): "Heron's Formula" s = 0.5 * (self.a + self.b + self.c) return math.sqrt( s * (s - self.a) * (s - self.b) * (s - self.c)) def getA(self): return math.acos((-self.a**2 + self.b**2 + self.c**2) / (2.0 * self.b * self.c)) def getB(self): return math.acos((self.a**2 - self.b**2 + self.c**2) / (2.0 * self.a * self.c)) def getC(self): return math.acos((self.a**2 + self.b**2 - self.c**2) / (2.0 * self.a * self.b)) A = property(getA, doc='Angle A in radians') B = property(getB, doc='Angle B in radians') C = property(getC, doc='Angle C in radians') area = property(getArea, doc="Triangle's area") >>> mytri = Triangle(3,4,5) >>> math.degrees(mytri.C) 90.0 >>> math.degrees(mytri.A) 36.86989764584402 >>> mytri.area = 6 Traceback (most recent call last): File "", line 1, in -toplevel- mytri.area = 6 AttributeError: can't set attribute Alex Martelli's example in 'Python in a Nutshell' is similar: a rectangle's area is computed on the fly (pg. 85). Note that defining attributes in this way doesn't mean we only find out an attribute is really a property much further along in the code (everything is expressed in one line) -- which was the problem decorators addressed i.e. a long function def might obscure the fact that we're defining a classmethod (the older f1 = classmethod(f1) had to come at the end). >>> help(Triangle) # now get us this useful section in the documentation: | -- | Properties defined here: | | A | Angle A in radians | | = getA(self) | | B | Angle B in radians | | = getB(self) | | C | Angle C in radians | | = getC(self) | | area | Triangle's area | | = getArea(self) | Heron's Formula | | -- I think it's fine to call it "syntactic sugar" when we make object attributes call their associated accessors and mutators behind the scenes. Conceptually, we're giving the user of the class a simpler API while giving ourselves as programmers a lot of control over what triggers what. It's easy to think of angles and area as attributes, even if we don't allow them to be set except through changes to edges. Why should we force a user to remember what's a method and what's not, given edges, angles and area (could add perimeter too). A weakness in the above design: we only check for violations of triangle inequality in the constructor, yet allow changes to a,b,c through the API. Kirby ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Arthur > > What beyond sugar for leaving off a "()" when trying to retrieve a value > from a method are we accomplishing by using properties? I have tended to > look at properties mostly an accommodation to those coming from other > languages which have something similar, but never as something that was > core > to Python or a Pythonic approach to things. Am I missing something > fundamental? The searching I do on this point only confirms to me that my own confusion is well shared - perhaps indicating this to be an area not totally OT for this forum. Ray Hettinger's "How-To Guide for Descriptors" http://users.rcn.com/python/download/Descriptor.htm covers properties, but the use case given is extremely unsatisfying - essentially offering a situation where a fundamental design change has been made to a program in mid-stream, and since properties were used in the initial design, the change can be made with little refactoring. Somehow I don't expect a programming language to accommodate the possibility of a midstream change in a programs design/intentions of the kind cited here. New design, and the expectation would be to need to recode to the new design. All within bounds, of course. OOP, I think, does try to address this issue to a reasonable degree. But the properties use case in this article is, to my intuition, a stretch beyond those reasonable bounds. I can't believe that a language or coding style intended to accommodate the range of possibilities for the kind of fundamental midstream redesign referenced in this use case could lead anywhere else but to some kind of madness. The fact is that I do use properties to a limited degree in PyGeo - the actual implementation of properties being trivial enough. Much less trivial is the why and when. The brain dead use of properties in PyGeo being definitely on my list for refactoring. Just not sure whether I should be consistent in avoiding them, or consistently using them, or when is which and which is when. Art ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Scott David Daniels > > Here's how to do the angles in 2.4 w/ properties: > > > @property > def A(self): > return math.acos((-self.a**2 + self.b**2 + self.c**2) >/ (2.0 * self.b * self.c)) Hmmm... We seem to be saying that @property works out-of-the box as a decorator in 2.4 - at least where we want read only properties. I can only assume that this is more of a side-effect of the introduction of decorators, than a feature fully designed into the language. Which is not to say that it is not a fortunate side effect. But it is unfortunate combo for me - since I never fully understood the purpose of properties, and don't fully get the mechanics of decorators. My most important points of confusion: What beyond sugar for leaving off a "()" when trying to retrieve a value from a method are we accomplishing by using properties? I have tended to look at properties mostly an accommodation to those coming from other languages which have something similar, but never as something that was core to Python or a Pythonic approach to things. Am I missing something fundamental? and Am I correct that the use of property as a "built-in" decorator is not designed into the language - at least in the same way that @classmethod has been? What would it take to create a @property decorator that allows one to set as well as get? Would we want to? Art ___ Edu-sig mailing list [EMAIL PROTECTED] http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> Now you can do: > > t = Triangle(3,4,5) > t.c, math.degrees(t.C) > t.a/math.sin(t.A), t.b/math.sin(t.B), t.c/math.sin(t.C) > t.b = t.c = 3 > t.c, math.degrees(t.C) > t.a/math.sin(t.A), t.b/math.sin(t.B), t.c/math.sin(t.C) > > This takes advantage of the fact that property with a single parameter > defines only the "get value" accessor, and makes setting or deleting > the property illegal. > > -- Scott David Daniels > [EMAIL PROTECTED] Totally excellent Scott. Thank you. Kirby ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
Kirby Urner wrote: > I’ve been thinking that a good way to introduce program design might involve > objects of type Triangle, i.e. instances of the Triangle class. > Anyway, here's a design question: do we want to compute the angles and > store them as properties at the time of construction, i.e. in the init? Or > do we want to make getAngles() a method? Compromise: call _getAngles from > the init. Here's how to do the angles in 2.4 w/ properties: class Triangle(object): def __init__(self, a,b,c): "Construct a triangle" if (c >= a + b) or (a >= b + c) or (b >= a + c): raise ValueError("Illegal edges: %s/%s/%s" % (a, b, c)) self.a = a self.b = b self.c = c def area(self): "Heron's Formula" s = 0.5 * (self.a + self.b + self.c) return math.sqrt( s * (s - self.a) * (s - self.b) * (s - self.c)) @property def A(self): return math.acos((-self.a**2 + self.b**2 + self.c**2) / (2.0 * self.b * self.c)) @property def B(self): return math.acos((self.a**2 - self.b**2 + self.c**2) / (2.0 * self.a * self.c)) @property def C(self): return math.acos((self.a**2 + self.b**2 - self.c**2) / (2.0 * self.a * self.b)) Now you can do: t = Triangle(3,4,5) t.c, math.degrees(t.C) t.a/math.sin(t.A), t.b/math.sin(t.B), t.c/math.sin(t.C) t.b = t.c = 3 t.c, math.degrees(t.C) t.a/math.sin(t.A), t.b/math.sin(t.B), t.c/math.sin(t.C) This takes advantage of the fact that property with a single parameter defines only the "get value" accessor, and makes setting or deleting the property illegal. -- Scott David Daniels [EMAIL PROTECTED] ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig
Re: [Edu-sig] Design patterns
> -Original Message- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On > Behalf Of Kirby Urner > Sent: Friday, August 19, 2005 8:30 PM > To: edu-sig@python.org > Subject: [Edu-sig] Design patterns > > Anyway, here's a design question: do we want to compute the angles and > store them as properties at the time of construction, i.e. in the init? PyGeo emphasizes dynamism. So on the one hand I am anxious - for performance reasons - to push as much processing as I can into __init__. IOW, start-up time for a construction is much less a concern than the responsiveness when there is change, i.e. when a point of the construction is picked and moved and all the implications of that move needs be determined and all elements affected by it redrawn. And exactly for the same reason, there are clear constraints as to what I can in fact put in __init__. Everything intended to be dynamic needs to be in methods calculated on the fly. What I end up with to get decent performance is a patterns of registration. Part of __init__ for any element is a process with registers it on a chain of dependencies, so that when a point is in fact picked and moved the point knows what other elements of the construction depend - directly and indirectly - on its position and only those elements are recalced and redrawn. The moral of the story is, I think, it depends on what in more precise terms you are trying to do. The great fun of building PyGeo has been that I always had a pretty clear idea of what I was trying to do. Given that, it seemed a process of simply discovering the way to do it. That is as opposed to inventing the way to do it. The way to do it was pretty much dictated by the intent of the project, and was more and less sitting there. I have just needed to find it. Art ___ Edu-sig mailing list Edu-sig@python.org http://mail.python.org/mailman/listinfo/edu-sig