Monthly archive for March, 2013

The Great Plural Experiment

2013-03-31 22:24

You probably know very well that internationalization is hard. The mere act of translating the UI texts is actually one of the easiest parts, even though it’s not a pushover either. As one example: if your messages include quantities, you need to have some logic in place to choose different forms of nouns to go with your numbers. Fortunately, most frameworks already have that, as it’s a standard i18n feature.

Not every string message in your code is something to localize, of course. Log messages that are not visible to the user can be left alone in English – they should be, in fact. Coincidentally, though, those messages are also very likely to contain many numbers, often used as numerical quantities: things to do, things done, error count, and so on:

  1. INFO: database.py:442/init_database - 236 rows created

What if that number is 1?…

  1. INFO: files.py:132/process_files - 1 files processed

Oh well. That’s hardly the end of the world, isn’t it? Anyway, let’s just make the message slightly more universal:

  1. INFO: files.py:132/process_files - 1 file(s) processed

There, problem solved!

No worries, I haven’t gone insane. I know that no real-world software would put such a gold plating on something as irrelevant as grammar of its log messages. But it’s spring break, and we can be silly, so let’s have some fun with the idea.
Here I pose the question:

How hard would it be to construct a plural form of English noun from the singular one?

Consulting the largest repository of human knowledge (well, second largest) reveals that the rules of building English plurals are not exactly trivial – but not very complex either. There are exceptions to almost every rule, though, and a large body of exceptions in general. Still, you could expect to achieve at least some success by just disregarding them completely, and following the simple rules to the letter.

How high that success ratio would be, though?

Tags: , , , ,
Author: Xion, posted under Computer Science & IT » 4 comments

Annotating Android

2013-03-24 12:48

Coding for Android typically means writing Java, for all the good and bad it entails. The language itself is known of its verbosity, but the Android itself does not really encourage conciseness either.

To illustrate, look at this trivial activity that simply displays its application name and version, complete with a button that allows to close the app:

  1. public class VersionActivity extends Activity {
  2.     private TextView txtAppName;
  3.     private TextView txtAppVersion;
  4.     private Button btnExit;
  5.  
  6.     @Override
  7.     public void onCreate(Bundle savedInstanceState) {
  8.         super.onCreate(savedInstanceState);
  9.         setContentView(R.layout.version);
  10.  
  11.         txtAppName = (TextView) findViewById(R.id.app_name_text);
  12.         txtAppVersion = (TextView) findViewById(R.id.app_version_text);
  13.         btnExit = (Button) findViewById(R.id.exit_button);
  14.  
  15.         btnExit.setOnClickListener(exitButtonListener);
  16.  
  17.         PackageManager pm = getPackageManager();
  18.         try {
  19.             PackageInfo pi = pm.getPackageInfo(getPackageName(), 0);
  20.             txtAppName.setText(pi.applicationInfo.name);
  21.             txtAppVersion.setText(pi.versionName + " (" + pi.versionCode + ")");
  22.         } catch (NameNotFoundException wontHappen) {}
  23.     }
  24.  
  25.     private OnClickListener exitButtonListener = new OnClickListener() {
  26.         @Override
  27.         public void onClick(View view) {
  28.             finish();
  29.         }
  30.     };
  31. }

Phew, that’s a lot of work! While the IDE will help you substantially in crafting this code, it won’t help that much when it comes to reading it. You can easily see how a lot of stuff here is repeated over and over, most notably fields holding View objects. Should you need to change something about them or add a new one, you have to go through all these places.

Not to mention that it simply looks cluttered.

Android Annotations project logoWhat to do about it, though?… As it turns out there is a way to structure your Android code in a more succinct and readable way. Like a few other approaches to modern Java, it employs a palette of annotations. There is namely a project called Android Annotations that offers few dozens of them and aims to speed up Android development, making the code easier and more maintainable.

And it’s pretty damn good at that, I must say. Rewriting the previous snippet to use those annotations results in a class which looks roughly like this:

  1. @EActivity(R.layout.version)
  2. public class VersionActivity extends Activity {
  3.     @ViewById(R.id.app_name_text) TextView txtAppName;
  4.     @ViewById(R.id.app_version_text) TextView txtAppVersion;
  5.  
  6.     @AfterViews
  7.     void showApplicationInfo() {
  8.         PackageManager pm = getPackageManager();
  9.         try {
  10.             PackageInfo pi = pm.getPackageInfo(getPackageName(), 0);
  11.             txtAppName.setText(pi.applicationInfo.name);
  12.             txtAppVersion.setText(pi.versionName + " (" + pi.versionCode + ")");
  13.         } catch (NameNotFoundException wontHappen) {}
  14.     }
  15.  
  16.     @Click(R.id.exit_button)
  17.     void exitButtonClick() {
  18.         finish();
  19.     }
  20. }

Not only we have eliminated all the boilerplate, leaving only the actual logic, but also made the code more declarative and explicit. Some of the irrelevant entities has been completely removed, too, like the btnExit field which was only used to bind an event listener. Overall, it’s much more elegant and understandable code.

How about a bigger example? There is one on the project’s official page which looks pretty impressive. I can also weigh in my own anecdotal evidence of going through the Android game I wrote long ago and molding its code (a few KLOC) to work with AA. The result has been rather impressive, partially thanks to very light dependency injection facilities that the project provides, allowing me to replace many occurrences of Game.get().getGfx().draw(...); silliness with just gfx.draw(...);.

So in closing, I can recommend AA to all Android devs out there. It will certainly make your lives easier!

Tags: , ,
Author: Xion, posted under Computer Science & IT » 6 comments

Unexpectedly Clean Code

2013-03-16 13:37

There is this quite well known book, titled Clean Code. It is a very insightful work which I wholeheartedly recommend reading for any serious (or semi-serious) programmer.
The premise revolves around the concept of “cleanness” of code, which the author defines in various ways. Mostly it boils down to high signal-to-noise ratio and clear structure, where everything is neatly subdivided into smaller parts.

The idea is very appealing. For some it may even sound like a grand revelation; I know it was almost like that for me. But there is a bigger kind of meta-lesson to be learned here: the one of scope where such great ideas apply – and where they don’t.

You see, the Clean Code ideal works very well for certain kind of languages. The original examples in the book are laid down in Java and this is no coincidence. Java – as well as C, Go and probably few others – is not a very expressive language: lots of detailed busy work is often needed, even for conceptually simple tasks. And if several such tasks are lined up one after another, the reader is likely to drown in small details instead of seeing the bigger picture.

Those details are therefore one of the prime reasons why you may call some code “unclean”. To tidy up, they need to be properly encapsulated, away from a higher level overview. Hence it’s pretty common in Java to see functions like this one:

  1. private boolean areFoosValid(List<Foo> foos) {
  2.     for (Foo foo : foos) {
  3.         if (!foo.isValid()) {
  4.             return false;
  5.         }
  6.     }
  7.     return true;
  8. }

and think of them as good code, even if such a function is only used once. The goodness comes from the fact that they are relieving their callers from irrelevant loop minutiae, so that it’s easier to see why we need foos to be valid in the first place.

Yet, at the same time, if you saw a completely equivalent Python construct:

  1. def _foos_valid(foos):
  2.     for foo in foos:
  3.         if not foo.is_valid():
  4.             return False
  5.     return True

you would firstly curse at incompetence and lack of knowledge of whoever wrote it:

  1. def _foos_valid(foos):
  2.     return all(foo.is_valid() for foo in foos)

and then you would get rid of the function altogether:

  1. if not all(foo.is_valid() for foo in foos):
  2.     logger.error("Some foo is invalid!")
  3.     return

Why? Because the language is expressive enough for implementation itself to be almost as readable as the function call. Sure, throw the result of all(...) into a variable for even more self-documenting sweetness, but don’t put it in some far away place behind a standalone function. Such code may or may not be cleaner; it will definitely raise eyebrows, though.

And lack of astonishment is probably the most important metric.

Tags: , , ,
Author: Xion, posted under Programming » 3 comments

Making Flask’s url_for More Flexible

2013-03-11 0:32

Flask is one of the countless web frameworks available for Python. It’s probably my favorite, because it’s rather minimal, simple and easy to use. All the expected features are there, too, although they might not be as powerful as in some more advanced tools.

As an example, here’s how you define some simple request handler, bound to a parametrized URL pattern:

  1. from flask import abort, render_template
  2. from myapplication import app, db_session, Post
  3.  
  4. @app.route('/post/<int:post_id>')
  5. def blogpost(post_id):
  6.     post = db_session.query(Post).get(post_id)
  7.     if not post:
  8.         abort(404)
  9.     return render_template('post.html', post=post)

This handler responds to requests that go to /post/42 and similar paths. The syntax for those URL patterns is not very advanced: parameters can only be captured as path segments rather than arbitrary groups within a regular expression. (You can still use query string arguments, of course).

On the flip side, reversing the URL – building it from handler name and parameters – is always possible. There is a url_for function which does just that. It can be used both from Python code and, perhaps more usefully, from HTML (Jinja) templates:

  1. <h2>Recent posts</h2>
  2. <ul>
  3.   {% for post in posts %}
  4.     <li>
  5.       <a href="{{ url_for('blogpost', post_id=post.id) }}">
  6.         {{ post.title }}
  7.       </a>
  8.     </li>
  9.   {% endfor %}
  10. </ul>

Parameters can have types, too. We’ve seen, for example, that post_id was defined as int in the URL pattern for blogpost handler. These types are checked during the actual routing of HTTP requests, but also by the url_for function:

  1. pattern = url_for('blogpost', post_id='<id>')  # raises ValueError

Most of the time, this little bit of “static typing” is a nice feature. However, there are some cases where this behavior of url_for is a bit too strict. Anytime we don’t intend to invoke the resulting URL directly, we might want a little more flexibility.

Biggest case-in-point are various client-side templates, used by JavaScript code to update small pieces of HTML without reloading the whole page. If you, for example, wanted to rewrite the template above to use Underscore templates, you would still want url_for to format the blogpost URL pattern:

  1. <h2>Recent posts</h2>
  2. <ul>
  3.   < % _.each(posts, function(post) { %>
  4.     <a href="{{ url_for('blogpost', post_id='<%= post.id %>') }}">
  5.         < %- post.name %>
  6.     </a>
  7.   < % }); %>
  8. </ul>

Assuming you don’t feel dizzy from seeing two templating languages at once, you will obviously notice that '< %= post.id %>' is not a valid int value. But it’s a correct value for post_id parameter, because the resulting URL (/post/< %= post.id %>) would not be used immediately. Instead, it would be just sent to the browser, where some JS code would pick it up and replace the Underscore placeholder with an actual ID.

Unfortunately, bypassing the default strictness of url_for is not exactly easy.

Tags: , , , ,
Author: Xion, posted under Computer Science & IT » Comments Off on Making Flask’s url_for More Flexible

When and What to Bash

2013-03-06 12:53

Often I advocate using Python for various automation tasks. It’s easy and powerful, especially when you consider how many great libraries – both standard and third party – are available at your fingertips. If asked, I could definitely share few anecdotes on how some .py script saved me a lot of hassle.

So I was a bit surprised to encounter a non-trivial problem where using Python seemed like an overkill. What I needed to do was to parse some text documents; extract specific bits of information from them; download several files through HTTP based on that; unzip them and place their content in designated directory.

Nothing too fancy. Rather simple stuff.

But then I realized that doing all this in Python would result in something like a screen and a half of terse code, full of tedious minutiae.
The parsing part alone would be a triply nested loop, with the first two layers taken by os.walk boilerplate. Next, there would be the joys of urllib2; heaven forbid it turns out I need some headers, cookies or authentication. Finally, I would have to wrap my head around the zipfile module. Oh cool, seems like some StringIO glue might be needed, too!

Granted, I would probably use glob2 for walking the file system, and definitely employ requests for HTTP work. And thus my little script would have external dependencies; isn’t that making it a full-blown program?…

Hey, I didn’t sign up for this! It was supposed to be simple. Why do I need to reimplement grep and curl, anyway? Can’t I just…

…oh wait.

Tags: , , ,
Author: Xion, posted under Applications, Programming » Comments Off on When and What to Bash
 


© 2023 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.