After my one-week rss detox, I was not surprised to find a 1000+ counter on my google reader. However, I couldn't digest it all an once due to (well, due to the enourmous amount of posts, but also due to) safari's memory usage growing from 17 to 250 Mb by the simple act of scrolling. As it turns out, they know about the bug already, and, well, tried to fix it. But if I understood well, they didn't succeed :/
Monday, 24 December 2007
Wednesday, 12 December 2007
Rails, Rake, TestTask and Perversion of Control
Here's the story. Rake is a ruby-based DSL for building tasks. It's heavily used by Ruby on Rails, especially for database maintenance and testing. One of its use for testing is a use for testing _plugins_. The way rails does it is, well... let's say brings a few surprises.
To run the tests of all plugins you enter command rake test:plugins
, to run the test of a single plugin you provide an environment viariable using this syntax rake test:plugins PLUGIN=plugin_name
. Now, to write a rake task that runs a subset of tests, and does some additional job, you'd set the variable from within your code and programatically invoke the test task.
And this is what's not working. The problem is - all test tasks are evaluated before reading your file, and stored as a data. The particular task for running plugins simply generates all paths and stores it all in a huge hash (dictionary). After finding this out, all I was left to do was to copy rails' inner solution into my code. I don't like it much, though...
Autor: Konrad o 08:37 0 komentarze
Tuesday, 11 December 2007
Someone take me to USA, please?
I'm surprised I managed to blog about this sooner than Michael, but the list of approved PyCon talks has been published, and two of Resolver proposals got in! Congratulations!
The other thing is - with each lecture I read about I felt even worse on not attending the conference. They should forbid organising too awesome events in States:/
In desperate try to collect money for the flight, I added some google adverts to my blog. I switched also the feed to short form. Let me know if that's too irritating :)
Errata: Apparently, In excitement I missed the fact that actually there are going to be three resolver talks on PyCon.
Autor: Konrad o 13:02 2 komentarze
Friday, 7 December 2007
What's your google chart?
I decided to try out google new charting API. It's use is pretty straightforward - you simply a regular GET request and receive the chart in response. The nice part of it is sending actual values - you encode them as strings, so here's "helloWorld"
With strings you say? Let's check it!
http://chart.apis.google.com/chart?cht=lc&chs=200x125&chd=s:abcdefghijklmnopqrstuvwxyz
Cool. So, what's the picture for my name?
P.S. Forgot to mention before: Resolver Beta is out!
Autor: Konrad o 03:22 0 komentarze
Thursday, 6 December 2007
Cool!
rigmor:~ konrad$ easy_install antigravity
Searching for antigravity
Reading http://pypi.python.org/simple/antigravity/
Reading http://fabien.schwob.org/antigravity/
Best match: antigravity 0.1
Downloading http://pypi.python.org/packages/source/a/antigravity/antigravity-0.1.zip#md5=371367b1f429f8fe19857c5eef1de491
Processing antigravity-0.1.zip
Running antigravity-0.1/setup.py -q bdist_egg --dist-dir /tmp/easy_install-pBpmRT/antigravity-0.1/egg-dist-tmp-megUd7
zip_safe flag not set; analyzing archive contents...
Adding antigravity 0.1 to easy-install.pth file
Installed /Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/site-packages/antigravity-0.1-py2.5.egg
Processing dependencies for antigravity
Finished processing dependencies for antigravity
rigmor:~ konrad$
Autor: Konrad o 06:47 0 komentarze
Wednesday, 5 December 2007
PWNED!
Yep, looks like my toy automata project needs no further work. Someone has already done it (reddited yesterday).
Autor: Konrad o 00:39 0 komentarze
Friday, 30 November 2007
"@apply antipattern" or "Python doesn't need a with_statement!"
Remember the new funky open syntax?
with open("somefile","r") as f:
print f.readlines()
It looks very pretty and ensures that the file gets closed after usage. Neat. However, nothing stops us from writing a decorator that does similar job without importing from __future__:def opened(*args):
def decorator(function):
def ret():
f = open(*args)
try:
function(f)
finally:
f.close()
return ret
return decorator
I know what it looks like. Even though, it makes us able to write simply:@opened("file.txt", "r")
def do_it(f):
print f.readlines()
do_it()
or even:@apply
@opened("file.txt", "r")
def do_it(f):
print f.readlines()
You see now why Guido doesn't like functional programming.
Autor: Konrad o 05:50 0 komentarze
Saturday, 24 November 2007
"With" statement comes handy with OpenGL
OpenGL programming in python may be painful in some situations. The reason for that is openGL's specific interface. Let me show you:
// C code that draws a triangle
glBegin(GL_TRIANGLES);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glEnd();
# the same code in python
glBegin(GL_TRIANGLES)
glVertex3f( 0, 1, 0)
glVertex3f(-1, -1, 0)
glVertex3f( 1, -1, 0)
glEnd()
Now we can make this code a bit clearer using the 'with' statement. Let's wrap glBegin and make it return a context which calls glEnd() after exiting the 'with' block. Having done that, we can write
# python code that draws a triangle
with glBegin(GL_TRIANGLES):
glVertex3f( 0, 1, 0)
glVertex3f(-1, -1, 0)
glVertex3f( 1, -1, 0)
Implementing such behaviour is very easy
from pyglet import gl as pyglet_gl
class GlEndCallingContext(object):
def __enter__(*_): pass
def __exit__(*_): pyglet_gl.glEnd()
def glBegin(*args):
pyglet_gl.glBegin(*args)
return GlEndCallingContext()
In fact, we can go even further and make all glFunctions return some dummy context. We could then add indentation after functions that don't need closing, just in case the overall view of the code should benefit:
with glColorf3(1, 0, 0):
glVertexf(0, 0, 0)
...
I implemented first 5 nehe tutorials in that way, using a wonderful pyglet library.
Autor: Konrad o 04:10 0 komentarze
Sunday, 4 November 2007
Painless module monkey-patching
One of Python's great advantages is its absolutely dynamic nature, which enables you to alter many objects (including modules) in runtime. This is particularily useful for testing since you can monkey-patch your module before exercising the SUT and make your tests way more granular.
However, the process has drawbacks, the biggest of which is its tendency towards verbosity. In order to not break other tests in a suite, you need to store the original attributes of the module and set them again after excercising the SUT. And to make sure the module _will_ be fixed you need a try-finally clause. With more than one modules this can lead to a several headache.
So, driven mad by a need to write 40-line test method excercising 4-liner, I imagined a dream-interface for that. What I came up with, besides the module-mocking power offered a mocha-like interface for mocking other objects as well. I have to say, I'm pretty damn proud of the result.
class Automaton(object):
...
def save_in_png(self, filename):
f = open('/tmp/graph.dot', "w")
f.write(self.as_dot())
f.close()
subprocess.check_call(['dot', '-Tpng', '-o', filename, '/tmp/graph.dot'])
class AutomatonTest(unittest.TestCase):
...
def test_save_in_png(self):
a = Automaton({(1, 'a'): [2, 3], (2, 'b'): [3]}, 1, [2, 3])
mock = Mocker(self)
mockfile = mock.object('file').expects('write', args=['beetle']).expects('close')
mock.function_in_module('subprocess.check_call',
args=[['dot', '-Tpng', '-o', 'ladybird', '/tmp/graph.dot']])
mock.function_in_module('__builtin__.open',
args=['/tmp/graph.dot', 'w'],
returns=mockfile)
mock.method(a, 'as_dot', args=[], returns='beetle')
mock.run(a.save_in_png, 'ladybird')
If the test fails, the mocker tries to be helpful again:
Traceback (most recent call last):
File "automaton_test.py", line 77, in test_save_in_png
mock.run(a.save_in_png, 'biedronka')
File "/Users/konrad/dev/sandbox/automata/mocking.py", line 73, in run
'Calls listing of %s fails: \nactual: %s\nexpected: %s' % (key, pretty(invoke_dict['actual_calls']), pretty(invoke_dict['expected_calls'])))
AssertionError: Calls listing of file.close fails:
actual: <No calls>
expected: file.close()
Autor: Konrad o 14:51 0 komentarze
Friday, 2 November 2007
GraphViz fun
I'm writing a tiny toy project involving automata, which was a good excuse to learn the dot language finally. I used GraphViz couple of times before and was very fond of it. After trying out several approaches I decided to put down all things I needed in order to get my automata graphs render as needed. These were:
- Print the epsilon character.
- Switch the orientation to horizontal (it's vertical by default).
- Render a double circle node.
- Render several graphs in a single plot.
- Have invisible nodes.
- Have invisible edges.
Having all this before my eyes, it became obvious that the only way to learn how to do it is by example, which is exactly what entered in google. I found this amazing flickr set with examples addressing almost all my problems. So here are the answers:
- Print the epsilon character.
- You can use html entities in your labels
- Switch the orientation to horizontal.
- Pass the directive rankdir=LR
- Render a double circle node.
- node [shape=doublecircle]
- Render several graphs in a single plot.
- This one was actually not a problem at all - if your nodes don't connect, you get an unconnected graph
- Have invisible nodes.
- node [shape=plaintext label=""]
- Have invisible edges.
- edge [style=invis]
So, the presentation's ready. Time to start writing the algorithm :)
Autor: Konrad o 12:19 1 komentarze
Saturday, 20 October 2007
TDD advocacy
I'm kind of ashamed of writing a "hreffy" post, but I just found a nice article about testing your code and keeping its design clean.
Autor: Konrad o 00:28 0 komentarze
Friday, 28 September 2007
Test notifications in gnome
I was quite impressed about rails/mac folks creating fancy test notifications by simply connecting zentest/autotest with growl. I wondered how can I get something similar in gnome. As it turns out - it's pretty straightforward - involves only 4 lines of python code and works using dbus. It uses one of the parts freedesktop.org - NotifyService. I created a tiny script for that. It looks rather nice and integrates well (the same service is used by gajim or rhythmbox).
Here's how you invoke it: konrad@machine:~$ python ./bin/test_notifier/test_notifier.py pass 'Test passed' "4 tests
9 assertions
0 failures
0 errors"
konrad@machine:~$ python ./bin/test_notifier/test_notifier.py fail 'Test failed' "4 tests
9 assertions
2 failures
0 errors"
And the code itself (btw: forget about 4 lines - here comes error handling:>)
import sys
import dbus
from os import path, getcwd
try:
status, title, message = sys.argv[1:]
icon_filename = {'pass': 'passed.png', 'fail': 'failed.png'}.get(status)
except Exception:
print 'Usage:\n\t\ttest_notifier [fail|pass] title message'
exit(0)
bus = dbus.SessionBus()
notifyService = bus.get_object("org.freedesktop.Notifications",
'/org/freedesktop/Notifications')
interface = dbus.Interface(notifyService,
'org.freedesktop.Notifications')
icon_filename = path.join(getcwd(),
path.dirname(__file__),
icon_filename)
interface.Notify('test_runner', 0,
icon_filename,
title, message,
[], {}, -1)
Autor: Konrad o 04:44 1 komentarze
XP reflections
While accumulating XP culture, I was a bit taken aback by the "don't think forward (more than one day)" rule. I couldn't quite understand why I shouldn't implement my functionality in more modular way (which would make future changes easier) even if I was _sure_ the future changes will be introduced. I stopped thinking about it at some moment, and really recently found the reason: finding the correct design of your system (i.e. one that makes changes easy) is impossible before you actually find yourself introducing them. In other words: since you always end up changing your design, don't mind for the future. YAGNI...
Autor: Konrad o 02:50 0 komentarze
Resolver rocks!
John Udell took a first look at resolver, and he loves it! The entry is followed by a screencast showing what Resolver can do. I had an impression, that John was taken by the possibility of keeping python objects in the grid and interacting with them in non-ordinary way (which gives some more interesting ideas, like enabling drag-n-dropping objects attributes from within say, cell's context menu [ - hey? Clerkenwell? Anyone? :D]).
It looks like the screencast was taken through VNC, so the window decorations look mediocre (this screenshot from resolver hacks depicts what it should look like). Still, the fact, that resolver gains interest gives me some childish joy :D
Autor: Konrad o 02:23 1 komentarze
Sunday, 23 September 2007
PyCon UK - late review (part 3, last :>)
There were several interesting talks in the conference. Last two lectures I want to write about are Jonathan Hartley's TDD talk, and Simon Willison's OpenID keynote.
I had opportunity to work with Jonathan for the last two months, so I pretty much imagined what he was going to say. I couldn't quite imagine how. I mean: ok, it's fun, but how can you describe it? John somehow managed to present it in a really interesting manner, giving step-by-step examples to let you feel what you're doing, and providing clear graphs to let you grasp the whole idea. In fact, I liked the graphs so much that I think someone should write a script to generate such things for everyday coding.
I saved to the end Simon Willison's OpenID keynote. Simon is one of the creators of django (I mean: the _really_ first creators :>), a web developer, and (effectively) an OpenID evangelist. His mindblowing speaking skills along with enormous amount of concised information and the fact that everyone attended the lecture (keynote) made openID to stay in minds of all PyConners.
Autor: Konrad o 14:28 1 komentarze
Wednesday, 12 September 2007
PyCon UK - late review (part 2)
On the first day, between 11:30am and 1:00pm, there were two other interesting talks: one ebout PyPy by Michael Hudson and the other about Stackless by Christian Tismer.
PyPy
PyPy is python compiler written in python. I heard of it before, but never got quite interested. However, the talk changed it a dramatically. We've been presented bunch of exciting features that PyPy enables, that being: dynamic sandboxing, objects becoming other objects, dynamic parser changes (evil but fun :>) and many others. I like the idea of running PyPy in any python implementation in order to compile python scripts to native format (which means: assembly, .net intermediate language, java bytecode or some crazy stuff like javascript, or python itself [sicko]). I _really_ like the idea of running PyPy in any python implementation in order to compile PyPy itself into assembly. Unfortunately, the JIT compiler is still being developped, so we'll have to wait a for that.Stackless
Stackless python is python implementation that removes GIL and introduces lightweight threads. This gives you a couple of new possibilities, one of which is to mime Erlang :P (and that's actually pretty good, since erlang's syntax doesn't appeal to me). There are some projects that make heavy use of stackless, the most famous probably being Eve online (where each player has his of her very own thread, yeah!). And there's one interesting pearl: there is a version of stackless, that's implemented on PyPy framework.Autor: Konrad o 03:02 0 komentarze
Tuesday, 11 September 2007
PyCon UK - late review (part 1)
PyCon UK ended on Sunday. Unfortunately, I didn't have any machine on my during the conference. That's why my review is a bit late.
The first thing to say - it was awesome. Two days of extremely interesting talks and conversations with a bunch (200) of incredibly smart people. Some of the talks definitely need mentioning.
Resolver
I'll begin with lectures given by my colleagues. First one: The New Age of the Amateur by Giles Thomas was a presentation of Resolver - an advanced spreadsheet application we're working on. It is believed to solve many problems that excel power user have today. I have never had an opportunity to look at Resolver from potential user's point of view and, I must say, it was positively surprising experience.Silverlight
Second event I attended was Michael's talk on Silverlight. Silverlight is Microsoft's "flash killer" product. What's interesting - very much in a manner C# was created, they managed to avoid mistakes made by their predecessors. I really like Silverlight's ability to be scripted in more than one language (including python, ruby and - I guess - any .net language). What's more, Silverlight apps should be able to run on Linux. Mono guys did an enormous feat implementing large part of Silverlight in Moonlight in a remarkable 21-day-long sprint. Moonlight is aiming to provide full implementation soon, but obviously it's not a matter of one month any more. The talk was very interesting. Michael did a great job playing with Silverlight before, and certainly knew what he was talking about. I'm very excited on his proof-of-concept Web IDE.Autor: Konrad o 06:24 0 komentarze
Thursday, 6 September 2007
What is the *exact* distinction between Model and View in MVC?
Couple of days ago, we encountered simple problem: Whether spreadsheet selection should be stored in model or in view. It seems obvious that the right place for it is the view, since data doesn't change with selection. Fine, but how do we know what the data is. In particular: how do we know that the selection is not part of it. I mean: It's clear isn't it. If it's clear, there should be a simple answer to the original question.
Quite an easy take is "data is what gets saved". Unfortunately, excel saves the selection along with the rest of the file. Since the saving criterion is useless, how about other apps using your data? Nope. There's nothing that prevents other apps from reading your selection state if it was saved. Our definition seems to escape.
Let me repeat what I want to achieve. Considering spreadsheet application: you got the model, which describes the content of each cell in each sheet, and you got the view, which tells you which part of the sheet you are watching right now. Since the view has a state, it needs to have it very own MVC to keep a track of it. So, what prevents us from merging view state (view model) into the data model (*the* Model)? The feeling, that it's wrong? Fine, but why you get that feeling? Why? WHYYYY? (this is the shot from 30 meters above [and receding] of a man on his knees crying in void. Never mind.)
Let's use maths. View is a projection of the real object (the data/model). Being a projection, it loses parts of the information. Does that analogy help us with the selection problem? Not really.
I spent some time thinking on this, investigating few other ideas, but in the end I gave up. I couldn't find any definition that was not tautological or simply wrong. The final conclusion is somewhat sad: there's no such thing as clear distinction. It's just like the zero being a natural number problem: it's a matter of taste, a matter of deal.
And why I had the feeling for obvious distinction? Most probably from the paper spredsheet analogy. Spreadsheets are so easy to grasp mainly because you can imagine them as pieces of papers.
More important consequence from that is that you'll never know if your MVC splitting was the right one. There are only practical issues. You may follow the way your brain tells you or not. You will never know if you were right. You will only know eventually that you were wrong. Now this is sad...
P.S. What makes life endurable here is agile appreach(yeah!), but this is a topic for other post.
Autor: Konrad o 02:35 0 komentarze
Wednesday, 29 August 2007
Python is neat
You know that nice feeling, when your language lets you transform your task into one line of code while still being readable? I needed to strip the quoted substrings from input string. The task was pretty easy, since there was no escaping, or nesting quotes. And I know, I can see it's more than one line: it requires a little bit of imagination :).
def removeQuotedSubstrings(origString):
return ''.join(x for num, x in
enumerate(origString.split('"')) if num % 2 == 0)
Autor: Konrad o 03:48 0 komentarze
Tuesday, 28 August 2007
Regex GUI utility done right
It's a pity that in spite of regular expressions' power we didn't have any graphical regex matching tools for a long time. Having GUI enables you to do some pretty nice stuff, like marking captured sections, and performing live substitution. Thankfully, someone finally did it. My only wish is to enable it to generate regexps for series of similar lines (like here).
Autor: Konrad o 06:44 0 komentarze
Wednesday, 22 August 2007
Scala's interoperability with Java is indeed a good thing.
OK. I have never written anything in Scala so this is rather general feeling, but the topic is general as well. Just today a, well... strange post got reditted. Someone by nick Pinderkent claims it's not good for Scala interoperate with java. I totally don't get his point. In much simplified version, it goes: java libraries don't have suitable functional interface, therefore, screw java.
So, how could one actually "look past Scala's java roots"?
Let's imagine Scala out of JVM. I'm not an expert on this, but I suspect, there's nothing that prevents us from compiling it into native assembly (well, except for lack of compiler:>). Such a Scala would do pretty much what C++ does now, but on slightly higher level and with bigger assemblies produced (garbage collection). It sounds nice, but the absolute lack of any low-level libraries makes it not worth the shot.
Creating new virtual machine is also not worth the effort, since from what we've seen over last years: it is a huge marketing task. Besides, it is better to have less VMs than more.
If you want to keep Scala running on JVM and just sweep the interoperability out. All what you get is a good language without any libs. That's a big no-no.
It's more than ten years now since industry began switching to virtual machines. One of advantages of that switch is the possibility of having not only different libraries but also different programming languages speak using common interface. For emerging languages, this is a huge opportunity. Let's not reject that! The argument for not using java libraries directly is perfectly fine: their interface sucks for Scheme developer, but the argument against writing wrappers around them appears to be a feeling rather, not a thought-through statement: "use of such adaptor code often leads to messy software". Eeee, no? It doesn't? Take a look at swing. It's a widget toolkit that was first implemented in java as a wrapper around awt (the older and miserable-looking GUI lib). With time it came into java's standard library and in jvm version 1.6 was completely rewritten in order to make it more effiicient. Isn't it the best way of implementing libraires for Scala?
Besides that, java interoperability is one of Scala's killer apps, and one of its defining features ("bringing functional programming to the java world"). What's the point of losing that?
Autor: Konrad o 09:57 1 komentarze
Monday, 20 August 2007
Http POST handling using System.Net.HttpListener in IronPython
Sorry for longish title, but I feel that this post should be googlable. I happened to spend just too much time looking for this recently. In case you don't know how HttpListener works, I suggest reading this tutorial. If you are interested only in POST handling, here's the snippet:
from System.IO import StreamReader
from System.Web import HttpUtility
# Having HttpListenerContext in context
body = context.Request.InputStream
encoding = context.Request.ContentEncoding
reader = StreamReader(body, encoding)
nameValuePairs = HttpUtility.ParseQueryString(reader.ReadToEnd(), encoding)
# nameValuePairs contains now
# a dictionary-like object ready for further processing
Autor: Konrad o 15:18 2 komentarze
Friday, 17 August 2007
Why "Why OO Sucks" Sucks
I just had a strange experience. I read this article and became speechless. I fully respect Joe Armstrong and consider him to be an authority, but I couldn't agree with every_single_statement in his essay. The more I read it, the more suprised I was. Let's take a look at his objections:
- Data structure and functions should not be bound together - whaaaat? But don't we think this way? I mean: a dog has it's abilities, there is a distinction of a subject and an object. Armstrongsays that "Functions do things. They have inputs and outputs". He seems to forget that they have also doers and doees (btw: does the former word exist at all?). That really is the way people think.
- Everything has to be an object - what's wrong with that? It's quite comfortable to be able to treat anything as a, well, thing, when you need it.
- In an OOPL data type definitions are spread out all over the place - wait a minute, don't OOPL's suggest keeping your classes in single files? I guess, what irritates Armstrong are function definitions, which, in his opinion should be kept somewhere else, but that was previous point.
- Objects have private state - and that's the reason why threading in OOPLs sucks. True. But we should remember, why private state was introduced: The blessed encapsulation. The bigger part of whole IT business depends on _real_and_unavoidable_ hiding implementation from user. Sadly, not all software is open source(yet, hiaahaha:>).
Until now, everything was fine. I didn't agree with most thesis, but this could have been due to my ignorance. But then, when I got to Why OO was popular section, it was too much. It contains few ad-hoc thesis with no proofs and expects you to agree. And the conspiracy theory looks like some flying spaghetti monster thing. Besides: Armstrong seems not to believe in people (well, developers) too much, he thinks everyone was seduced to use the worse solution. A-a, I don't buy it.
If I should find reasons, why functional languages aren't in spread use today (as spread as OOPLs), I'd say it's because of their poor readability and, therefore, maintainability. Besides, they force you to abstract simply too much.
Even though, I pretty much like functional languages, but more as a mind training, than a candidate to conquer the industry.
P.S. I encourage you to read this post, which contains a much better critical view.
Autor: Konrad o 06:59 1 komentarze
Wednesday, 15 August 2007
Bwuahaha :D Erlang has andalso!
And orelse! Honestly: I don't know what's the problem with short-circuit logic. Everyone loves it, as it is the most intuitive way of calculating logical values. I can see no reason for providing language syntax for both alternatives as each can be emulated in the other:
value1 = fun1()
value2 = fun2()
if value1 and value2 then [something]
Will invoke both subroutines before checking. And:
if fun1() then if fun2() then [something]
Will operate in short-circuit manner. All this and/andalso [and:>] or/orelse stuff simply pisses me off. It smells Visual-Basicish
What's more: I can see no reason for not using short-circuit operators as default in erlang as they are needed only in guards, which by default __do_not_alter_data__. The only use case I can see for non-SC operators is raising exceptions in some cases, but that's sick and ugly:
[something] when X > 0 and 5/X > Y
This will fail if you pass X=zero because "and" is not SC. I wouldn't like to work with someone, who writes such code.
Disclaimer: I just began reading "Programming Erlang", so if there IS a reason for non-SC logic as default, I'll be forced to take everything back.
Autor: Konrad o 03:40 1 komentarze
Monday, 13 August 2007
How dynamic languages made testing obvious
I guess it's not a _really_ inventive thought. I've already heard about five times of strong testing instead of strong typing. However, there's yet another reason why testing and dynamic languages should be associated.
Testing gets child's easy when all your types are designed to change. Most techniques I can think of become simpler:
- While testing state, you can prepare your fixtures fast, in just few lines of code. The features that enable you doing that are (in python) named arguments and its "open kimono" philosophy. Ruby gives you similar range of abilities (but I don't feel like I can enumarate them here:>)
- Constructing mock objects, and monkey-patching is supported practically on language level in both python and ruby, with their module attributes subtitution, ruby's class opening and blocks and python's lambda. And duck typing of course.
- Dynamic languages are suitable for building DSLs, which made it possible to create great behaviour testing frameworks (think Rspec)
The inspiration for this post (except for my boss' suggestion:>) came from the book xUnit Design Patterns, which focuses more on staticly typed languages. As I someone pointed out one day: DPs depend very much on the language you're using. And that's exactly the situation with that book. Many patterns become redundant in dynamic languages as you get the needed features for free.
- Fixture teardown - in most cases is done by a garbage collector
- Dependency Lookup, Test-specific subclass - become redundant since you can easily get to your object's guts in runtime
- Test hook - it's not a problem to substitute your method with a function wrapping around it
- Encapsulating logic into an object in order to make it testable is not needed, since you can manipulate methods quite easily
The conclusion, except obvious: "let's test" or less obvious "let's do more testing" is: It's really pleasant to know the reasons for which you enjoy your job so much.
Autor: Konrad o 03:29 0 komentarze
Monday, 6 August 2007
Subtext
Whoops. Finally managed to try it out. It sucks :). Like most academic ideas, it's UI is far from intuitive. I guess Subtext has to wait for its Apple.
Autor: Konrad o 10:55 0 komentarze
Making code editing a better experience, part 2
Few ideas
Well, to be honest, I intended to split my previous article into two. This part was to describe some further ideas. All of them were addressing the same issue: handling repetitive code.
The first one could be called 'programming by example'. People (I at least) tend to think in examples. Why couldn't we make our languages and IDE's support it. You could write your function once just like you write any other code, and then, when you find out you could use it again, you do 'intelligent copy&pasting'. The code still looks quite dumb and easy (I mean: no loops were extracted) but the link exists and you make hard use of it when your code needs change.
The other idea was inspired by spreadsheets. I still remember how impressed I was on excel's unfolding characteristic values (I was around 10 then). When you enter '1' in one cell, and '2' in the cell below, you can grab the corner, and all following cells get filled with values 3, 4 etc. It worked even for months and weekdays!
Again: why couldn't we implement similar feature in some IDE? I know, that you don't use 1-10 enumeration very often, but if you could get your values filled from lists and other enumerables from within your code, that could do the job.
Yet another idea came from reflexions over lisp. I met too many people claiming that lisp is the king. Why did they say so? One of the killer features of lisp are of course macros. Unfortunately, they tend to become really hard to code in other languages. That's because most languages first need to get parsed into what's called Abstract Syntax Tree. Lisp is an AST itself. The parsing is dumb easy. That makes writing macros possible.
The idea is: if whatever we do, we do it on AST, why not interact with it directly? And no, I'm not talking about using lisp or scheme. I'm talking of a GUI that let's you drag&drop tree elements, fold and unfold them and visualize yourlogic this way.
The good news: subtext
Imagine my surprise, when I found out, that all these ideas are already in use. What's more: I have only scratched the surface. There's a whole new way of programming being built around that. For three years already! The conclusion is conditional: either I'm getting overexcited on something that's not so hot, or we're about to experience a big change soon...
Autor: Konrad o 06:16 0 komentarze
Wednesday, 1 August 2007
Making code editing better experience
What's the problem
The biggest pain I had for my first week at my First Real Job was writing and maintaining extremely repetive code, mainly in tests. The problem wasn't the wrong attitude. Resolver programmers follow all best practices, and besides they are really, really smart guys. The problem seems to appear, when the repetition is very small and local.
Let's say you've got a function taking 5 args. You want to invoke it 10 times with 2 arguments changing and 3 staying the same. The cost of encapsulating it into another function is small, but it's still bigger than using copy-pasting it. What's more: you often get _more_ readable code than extracting common parts. The conclusion is: generalization is good and helps you unless you're operating on a very small scale.
However, following the example: what if you spot an error in your not-changing parameters? You have two choices: either correcting the same 5-character mistake in every line, or using a regexp.
Regular expressions are not user-friendly
OK, so, as someone wise once said: You've got a problem. You decide to use regexp to solve it. Now you've got two problems. Regular expressions are relatively simple (after you learn it buhaha:>) yet powerful tool for automated text processing. You take your mistake repeated 10 times in your code, apply a regexp to it, and voila: everything's broken. You forgot some fancy-dancy character which spoils the whole thing. That's not a problem: you fix your regexp, and everything's fine. Yeah, but by this time you could have fixed your code two times manually.
I know, it's a matter of seconds if not less, but: 1. Seconds tend to acculumate fast; 2. It's a pain in the ass isn't it?
Ok, so how can we make using regexps faster? Two reasons why people don't use them in _really_ small changes are: 1. The time to find out and enter a regexp is often taking longer than adding changes manually; 2. Poeple tend to make mistakes, and debugging a thing that is to change 10 lines of code is WRONG! A solution which seem to get rid of both these problems is automated regexp generation. Of course, you can use it only in a subset of described problems, but I think it could do its job.
An example: managing the border in some GUI application. For some reason I had to set each Border in a seperate line:
a.LeftBorder = True
a.TopBorder = True
a.RightBorder = True
a.BottomBorder = True
I ran it and... KABOOM, an exception. Yeah, right it's not LeftBorder but BorderLeft etc. Not good. I fixed the code using mouse (okay, I didn't: I downloaded vim, installed it, retried the regexp 3 times, and got it replaced. Really). Anyway, I had pretty much time to imagine the tool I'd love to use. Something, that would get the lines, find the similarity and suggest a replacement, which I could then change _once_, without any entering any regexp. And all of it under ONE keystroke (ok, maybe two). Actually, I started looking for a way to find such similarities, and found Jacob Kaplan Moss' TemplateMaker, which could do the job.
I happened to reproduce the algorithm or, at least, something similar to it that would suit my requirements. I turned out to be pretty straitforward 15-liner. It should work best as a plug-in to your favourite text editor, but, since I wanted it to be portable, I wrote a seperate GUI (in wxPython - portability) for it. Some things which may surprise you are automatic clipboard capture on load, and clipboard filling on every replacement editing (couldn't find wxPythons onClose event), so you'll get an exception on copy-pasting replacement field. Anyway: Take a look:
Say you've got some text you want to refactor locally, like in the notepad (5) instance on the screenshot. You copy it, run the tool, which:
- captures the clipboard content and puts it into input text box (1)
- runs my templateMaker clone and finds a regexp that suits best to input lines (and puts it in box (2))
- gets the same expression in the form of replacement (with backreferences)
- runs the re.sub function, that generates output text (put then in (4))
The only thing you have to do is to change replacement (although there's nothing that prevents you from editing other fields, which is quite useful when the regexp was not guessed properly). As I mentioned before: the clipboard gets filled on every change of textbox (3), which is definitely a bug of mine (which should be corrected shortly :>). Have fun
Autor: Konrad o 06:31 1 komentarze
Saturday, 28 July 2007
Silly language design decisions.
Didn't know that before:
Perl's zipping operator
Every self-respecting dynamic language has a zipping function (or method). Python has its built-in zip(), haskell as well. Ruby gets it implemented as one of Array methods. I just didn't know (untill 3 days ago), that it's particularly useful for perl programers. Unfortunately, its name is THREE CHARACTERS LONG! O_o, that is waaay too many. That's why Larry Wall introduced zipping operator. You wonder what is it? Isn't that obvois? It's Yen symbol! Come on, it looks like a zipper anyway!
Genius.
Except for the fact, that there are _two_ Yen signs in unicode (¥ and ¥). And only one is recognised by the parser. Lame. Fortunately, Larry changes it to 'Z' in perl 6
Take a look on Jonathan's blog entry
And some quotes:
The zipper/yen operator has been renamed to Z. This is good for me, as I’ve never been very good at memorizing Vim’s digraphs.
Maybe we should avoid other symbols like this for sigils
BTW, the exact same thing happens with the Won sign ₩ on Korean Windows
systems; it is also mapped to 0x5c in the default codepage, and paths
are displayed with the Won sign instead of the backslash as separators.
Just something to keep in mind in case you are tempted to use the Won
sign as a sigil or operator in the future.
Cheers,
-Jan
Visual Basic AndAlso short circuit operators
Well, story is simple. When Visual Basic was designed, either no one knew about short circuit operators, or they didn't recognise their virtues. And years after, they couldn't stick it in because of backwards complatibility. But they found a solution eventually: AndAlso and OrElse operators. Simple, isn't it? AndAlso it doesn't break the compatibility. I only wonder why OrElse is OrElse and not... let's say OrPossibly or OrMaybe or OrHowAbout.
Autor: Konrad o 14:51 0 komentarze
Thursday, 12 July 2007
How to get a decent console under Windows
The reason
I had to switch to windows for some time and, after working under ubuntu for over a year, I finally realized what linux users meant when saying that win wasn't userfriendly. Linux' great power comes from its extensibility (obviously) and customizability. The poor support for the latter drives me mad every time I need to use win. It took me couple of days to set up a usable and useful console, so hereby I include the recipe.
Tabs and good look
Since being console under windows means running in one, to get a tabbed view we need to download a wrapper. Its name is, surprisingly, Console and the tabs feature is enabled in latest versions (Console2 has it, while 1.5 not. if you download the latest version (>2.0.131), you will get multiple shell support as well). There's no need to install. Just extract, run the Console.exe, et voila. Much prettier, isn't it. It is a good idea to put the folder in some appropriate place (like c:\Program Files\Console2).
Shell
Next thing we're gonna need is Powershell. I still haven't dicovered all its features, but tab completion, automatic slash-to-backslash convertion and aliases to many bash commands (including man and ls, yipeee!) makes it good enough for me. You can download it from microsoft's site. To get Console running with powershell you can use its options window (Edit/Settings...).
Multiple shell support
Console can use multiple shells. How does it work? Say, you prefer using powershell, but it's not fast enough for your machine. Or you use apps with command line interface quite often (python, mysql, irb). Here's how you can get Console to use all of them: open the console.xml file in your console dir, and find the <tabs> tag. Every tag is a preset for a type of console to open. There is only one <tab>...</tab> entry now. Duplicate it, and edit the shell attribute in the <console> inner tag. Here's what the section may look like afterwards:
<tabs>
<tab title="Powershell">
<console shell="powershell" init_dir=""/>
<cursor style="0" r="255" g="255" b="255"/>
<background type="0" r="0" g="0" b="0">
<image file="" relative="0" extend="0" position="0">
<tint opacity="0" r="0" g="0" b="0"/>
</image>
</background>
</tab>
<tab title="IronPython">
<console shell="ipy" init_dir=""/>
<cursor style="0" r="255" g="255" b="255"/>
<background type="0" r="0" g="0" b="0">
<image file="" relative="0" extend="0" position="0">
<tint opacity="0" r="0" g="0" b="0"/>
</image>
</background>
</tab>
<tab title="Python">
<console shell="python" init_dir=""/>
<cursor style="0" r="255" g="255" b="255"/>
<background type="0" r="0" g="0" b="0">
<image file="" relative="0" extend="0" position="0">
<tint opacity="0" r="0" g="0" b="0"/>
</image>
</background>
</tab>
<tab title="Windows shell">
<console shell="cmd.exe" init_dir=""/>
<cursor style="0" r="255" g="255" b="255"/>
<background type="0" r="0" g="0" b="0">
<image file="" relative="0" extend="0" position="0">
<tint opacity="0" r="0" g="0" b="0"/>
</image>
</background>
</tab>
</tabs>
Keyboard shortcuts
You get by default shortcuts Ctrl+F1, Ctrl+F2, etc. for shells you set. It's customizable (obviously). It is a useful trick to define hotkeys for launching Console, so that you can run it whatever window is active. There are plenty of hotkeys deamons for win, that let you do that. I'm using Hot Keys Plus
The final effect
Here it is.
Autor: Konrad o 15:58 3 komentarze