En Wed, 29 Aug 2007 07:32:21 -0300, BJörn Lindqvist <[EMAIL PROTECTED]> escribi�:
> On 8/24/07, Gabriel Genellina <[EMAIL PROTECTED]> wrote: >> En Thu, 23 Aug 2007 09:20:21 -0300, BJörn Lindqvist <[EMAIL PROTECTED]> >> escribi�: >> >> > def check_user_logged_in(func): >> > def f(*args, **kwargs): >> > if global_state.the_user.is_logged_in: >> > return func(*args, **kwargs) >> > return show_login_page() >> > return f >> >> I think there is a semantic problem, perhaps we are not talking >> about the same thing. I'm considering the software complexity AS >> PERCEIVED BY THE PROGRAMMER, looking at the interactions between a >> program and a programmer who is working on some task; some people >> would say "cognitive complexity" to make it clear. > > There is no semantic problem. You are just mistaken in your belief > that the complexity that the user of the decorator has to deal with is > different from the complexity in implementing the decorator. But they ARE different. That's the whole point of abstractions, code reuse, layered design... Designing a simple interfase on top of a complex system is very common. Nobody writes X-Window code, as nobody writes a raw event loop for Windows anymore: there are very good GUI toolkits, even portable frameworks, that put an abstract layer on top of that so the programmer has a much simple and coherent view. The complexity is behind the scenes. >> Which API is more complex: one in which you can play a movie with >> just a single call like PlayMovie(Title), or one on which you must >> call a zillion functions to firtly initialize the stream format, >> configure the display, disable undesired user interfase elements, >> locate the movie file, load it in chunks, etc.? The first one is >> certainly much simpler to use (simpler = less complex), and maybe >> internally it calls the same functions as the second one, but nobody >> cares. > > "nobody cares" is your guess. I'd bet that the caller of the PlayMovie > function cares a lot: Is the movie played full screened? Which > encodings are supported? Can you set the title of the movie window? Is > streaming supported? Does it even work on windows? Which URI schemes > does it support? And so on and so on. > > That is why no video decoding API:s have a PlayMovie(Title) function > and why I haven't seen a single 3d engine with a > MakeReallyCoolDoomCloneFPSGame() function. (yet!). What about urlopen? Using a single call one can be authenticated and retrieve any file in the other side of the planet. I consider it a simple interfase, altough it does complex things. Would you say it is better to use plain sockets everywhere? Or, since sockets are abstractions themselves, would you say it is better to use lower level primitives instead? Each time you descend a level, you have to use many simpler functions - but their combination is more complex. > "hiding details" only works if the client programmer really doesn't > care about the details. Why should he care? Isn't "hiding implementation details" a good design principle? When I use urlopen, I don't even care of the underlying socket implementation. I don't care which interfase the request is sent thru. I don't care if the answer got fragmented and some packets had to be reassembled. urlopen gives me something that looks like a file, and I just read() from it. >> Back to your example, the fact that a decorator builds a higher order >> function, does NOT make it more complex - because the programmer does >> not >> see that. In fact, hiding the details makes it simpler. > > Yes, the programmer does see that. The example decorator I posted > requires about a zillion preconditions to work correctly and will fail > in weird ways when those preconditions are not satisfied. The > programmer is interested in the crazy failures he or she will > experience. I dare you to try and implementing the code both as a > decorator and as a function, then write the unit tests and > documentation. The complexity of those three items together > (implementation + tests + documentation) will be much higher for the > decorator choice because the complexity of the decorator > implementation is a bit higher than using a plain old function. Testing the decorator is as hard as testing any other function. Testing the decorated functions might involve *only* checking if the decorator is actually used for those functions. Going to your posted example, I don't see the difference - I should say, I don't see the advantage. Using a decorator hides some implementation details and reduces coupling between modules, both good things on "my" book; your function with no decorator does quite the opposite, and doesn't look like good coding style (on "my" book, of course). > Note also that it is extremely rare to see well-documented or > well-tested code, which means that the programmer WILL have to analyze > the implementation which means that implementation complexity matters > a lot. In any case, that would require testing and analyzing ONE function (the decorator) instead of inspecting a zillion repetitions of the same code that, when being wrong, have to be located and fixed on all those places. Really, I still can't understand how you can defend such silly things - unless we are talking about different things. -- Gabriel Genellina -- http://mail.python.org/mailman/listinfo/python-list