Posts from 2013

Set the Returns Free

2013-07-24 19:02

Few pastimes are more pointless and unproductive than arguing about coding style. As long as the basic requirement of consistency is present, there is really next to nothing that wouldn’t fly. You may hear stories of certain… unusual approaches, like using 3-space indentation to “offend all equally”, but it still doesn’t give you the license to criticize – or worse yet, disobey. If you chose to contribute to a particular codebase, you follow the standard, period.

With this out of the way, I will go ahead to pick on my personal pet peeve by pointing out that the rule of single return from function is just dumb!… To my excuse, however, it is not really a stylistic rule, which is also one of the reasons I consider it inane. Since it changes the algorithmic structure of a function, it’s actually about semantics and should be treated as architectural guideline.

Even then, what’s wrong with avoiding more than one return statement? A couple of things come to mind.

It’s unnecessarily verbose

There is a particular “idiom” that you may encounter from time to time, especially in beginner’s code, or just code written by someone who had a particularly bad day. Here’s how it goes:

  1. bool isFooed() {
  2.     if (some != condition || thatMay(involve(foo))) {
  3.         return true;
  4.     } else {
  5.         return false;
  6.     }
  7. }

While it looks completely silly, its only felony is carrying the result through one more place than it’s absolutely necessary. But we would never write such a thing with clear mind. We would point it out immediately in code review. We would fix it whenever encountered.

And yet, it’s essentially the same pattern as in the code below:

  1. bool performSomeObscureAction() {
  2.     bool success;
  3.     if (startsAlignProperly()) {
  4.         // .. do stuff, followed by more stuff ...
  5.         success = true;
  6.     } else {
  7.         // ... report error, maybe do some cleanup ...
  8.         success = false;
  9.     }
  10.     return success;
  11. }

It has just one redundant layer of complexity: the success variable. We could remove it and replace the assignments to it by direct return true; and return false;. But that, of course, would violate the rule of single return point, and therefore code meant to follow it is stuck with flaws equivalent to having no idea how basic control statements and boolean logic works.

It reeks of Pascal stench

If we are happily condemning the use of more than one return statement, we could as well stay completely true to our beliefs. Why not prohibit all of such statements, and in fact use a language that just plain doesn’t support them?…

  1. function PerformAction : Boolean;
  2. begin
  3.     if canDo; then
  4.         { ... do stuff ... }
  5.         PerformAction := True;
  6.     else
  7.         PerformAction := False;
  8. end;

I’m totally baffled by any claims purporting that this technique makes code more readable. Not only the return value is now semi-hidden, disguised as one of the ordinary variable assignments, but also the return point itself is completely lost. An execution path may end inside an if inside while inside a switch, somewhere deep in the function innards, and you wouldn’t even notice without tracing all the closing braces end;s, or following the changes in indentation levels.
I’m all for disincentivizing long functions but really, there are much better ways to do that.

It gives the wrong impression

Although by far the most braindead, the rule of single return is unfortunately not the only one of its kind. There is a whole class of misguided principles that apply to certain flow control instructions: return, break and continue. What they share in common is the great potential of obfuscating the real meaning of some parts of the algorithms, simply because of forcing the code to be structured in a specific, rigid way.

Why it’s bad? Because one size does not fit all. Abusing early returns is hardly commendable:

  1. @Override
  2. public void onReceive(Context context, Intent intent) {
  3.     if (intent.getBooleanExtra(BatteryManager.EXTRA_PLUGGED, false)) {
  4.         resumeBackgroundTasks();
  5.         return;
  6.     }
  7.     stopBackgroundTasks();
  8.     // XXX: why "charger plugged" is more special state than "unplugged"?...
  9. }

but avoiding them at all costs won’t make the code better by any stretch:

  1. void read_config_file(const std::string& filename) {
  2.     std::ifstream ifs(filename):
  3.     if (ifs) {
  4.         // read the file ...
  5.         // ... parse the file ...
  6.         // ... remember config values ...
  7.         // ... and probably some other things too!
  8.     } else {  // (200 lines later)
  9.         log("cannot read config file: %s", filename);
  10.     }
  11. }

Since every function is different, trying to mold them into some over-specified template will just end awry.

Tags: ,
Author: Xion, posted under Computer Science & IT » Comments Off on Set the Returns Free

Python is the Worst Part of C++

2013-07-15 22:15

I’ve had a peculiar kind of awful realization after listening to a C++ talk earlier today. The speaker (Bjarne Stroustrup, actually) went over a few defining components of the language, before he took a much longer stop at templates. In C++14, templates are back in the spotlight because of the new constraints feature, intended to make working with (and especially debugging) templates much more pleasant.

Everyone using C++ templates now is probably well accustomed to the cryptic and excessively long error messages that the compiler spits out whenever you make even the slightest of mistakes. Because of the duck typing semantics of template arguments, those messages are always exposing the internals of a particular template’s implementation. If you, for example, worked with STL implementation from Visual C++, you would recognize the internal __rb_tree symbol; it appeared very often if you misused the map or set containers. Its appearance was at best only remotely helpful at locating the issue – especially if it was inside a multi-line behemoth of an error message.

Before constraints (or “concepts lite”, as they are dubbed) improve the situation, this is arguably the worst part of the C++ language. But alas, C++ is not the only language offering such a poor user experience. As a matter of fact, there is a whole class of languages which are exactly like that – and they won’t change anytime soon.

Yes, I’m talking about the so-called scripting languages in general, and Python in particular. The analogies are striking, too, once you see past the superfluous differences.

Take the before mentioned duck typing as an example. In Python, it is one of the core semantical tenets, a cornerstone of language’s approach to polymorphism. In current C++, this is precisely the cause of page-long, undecipherable compiler errors. You just don’t know whether it’s a duck before you tell it to quack, which usually happens somewhere deep inside the template code.

But wait! Python et al. also have those “compiler errors”. We just call them stacktraces and have interpreters format them in much a nicer, more readable way.
Of course unlike template-related errors in C++, stacktraces tend to be actually helpful. I pose, however, that it’s mostly because we learned to expect them. Studying Python or any other scripting language, we’re inevitably exposed to them at the very early stage, with a steady learning curve that corresponds to the growing complexity of our code.
This is totally different than having the compiler literally throw its innards at you when you try to sort a list of integers.

What I find the most interesting in this whole intellectual exercise is to examine what solutions are offered by both sides of the comparison.
Dynamic languages propose coping mechanisms, at best. You are advised to liberally blanket your code with automated tests so that failing to quack is immediately registered before the duck (er, code) goes live. While some rudimentary static analysis and linting is typically provided, you generally cannot have a reasonable idea whether your code doesn’t fail at the most basic level before you actually run it.

Now, have you ever unit-tested the template specification process that the C++ compiler performs for any of your own templates? Yeah, I thought so. Except for the biggest marvels of template metaprogramming, this may not be something that even crosses your mind. Instead, the established industry practice is simply “don’t do template metaprogramming”.

But obviously, we want to use dynamic languages, and some of us probably want to do template metaprogramming. (Maybe? Just a few? Anyone?…) Since they clearly appear to be similar problems, it’s not very surprising that remedies start to look somewhat alike. C++ is getting concepts in order to impose some rigidity on the currently free-form template arguments. Python is not fully on that path yet but the signs are evident, with the recent adoptions of enums (that I’ve fretted about) as the most prominent example.

If I’m right here, it would be curious to see what lies at the end of this road. In any case, it will probably have been already invented fifty years ago in Lisp.

Tags: , , , , ,
Author: Xion, posted under Programming » Comments Off on Python is the Worst Part of C++

Testing Jinja Templates

2013-07-06 21:43

If you use a powerful HTML templating engine – like Jinja – inevitably you will notice a slow creep of more and more complicated logic entering your templates. Contrary to what many may tell you, it’s not inherently bad. Views can be complex, and keeping that complexity contained within templates is often better than letting it sip into controller code.

But logic, if not trivial, requires testing. Exempting it by saying “That’s just a template!” doesn’t really cut it. It’s pretty crappy excuse, at least in Flask/Jinja, where you can easily import your template macros into Python code:

  1. {% macro hello_world() %}
  2.     Hello world!
  3. {% endmacro %}
  1. import flask
  2. hello_world = flask.get_template_attribute('hello.html', 'hello_world')
  3. print hello_world()

When writing a fully featured test suite, though, you would probably want some more leverage Importing those macros by hand in every test can get stale rather quickly and leave behind a lot of boilerplate code.

Fortunately, this is Python. We have world class tools to combat repetition and verbosity, second only to Lisp macros. There is no reason we couldn’t write tests for our Jinja templates in clean and concise manner:

  1. class Hello(JinjaTestCase):
  2.     __template_imports__ = {
  3.         'hello_world': 'hello.html',
  4.     }
  5.  
  6.     def test_hello_world(self):
  7.         result = self.hello_world()
  8.         self.assert_in("hello", result.lower())
  9.         self.assert_in("world", result.lower())

The JinjaTestCase base, implemented in this gist, provides evidence that a little __metaclass__ can go a long way :)

Tags: , , , ,
Author: Xion, posted under Programming » Comments Off on Testing Jinja Templates

Fluent Chaining

2013-06-30 14:24

Look at the following piece of jQuery code:

  1. $('span')
  2.     .attr('data-type', 'info')
  3.     .addClass('message')
  4.     .css('width', '100%')
  5.     .text("Hello world!")
  6.     .appendTo($('body'))
  7. ;

Of the two patterns it demonstrates, one is almost decisively bad: you shouldn’t build up DOM nodes this way. To get more concise and maintainable code, it’s better to use one of the client-side templating engines.

The second pattern, however, is hugely interesting. Most often called method chaining, it also goes by a more glamorous name of fluent interface. As you can see by a careful look at the code sample above, the idea is pretty simple:

Whenever a method is mostly mutating object’s state, it should return the object itself.

Prime example of methods that do that are setters: simple function whose pretty much only purpose is to alter the value of some property stored as a field inside the object. When augmented with support for chaining, they start to work very pleasantly with few other common patterns, such as builders in Java.
Here’s, for example, a piece of code constructing a Protocol Buffer message that doesn’t use its Builder‘s fluent interface:

  1. Person.Builder builder = Person.newBuilder();
  2. builder.setId(42);
  3. builder.setFirstName("John");
  4. builder.setLastName("Doe");
  5. builder.setEmail("johndoe@example.com")
  6. Person person = builder.build();

And here’s the equivalent that takes advantage of method chaining:

  1. Person person = Person.newBuilder()
  2.     .setId(42)
  3.     .setFirstName("John")
  4.     .setLastName("Doe")
  5.     .setEmail("johndoe@example.com")
  6.     .build();

It may not be shorter by pure line count, but it’s definitely easier on the eyes without all these repetitions of (completely unnecessary) builder variable. We could even say that the whole Builder pattern is almost completely hidden thanks to method chaining. And undoubtedly, this a very good thing, as that pattern is just a compensation for the deficiencies of Java programming language.

By now you’ve probably figured out how to implement method chaining. In derivatives of C language, that amounts to having a return this; statement at the end of method’s body:

  1. jQuery.fn.extend({
  2.     addClass: function( value ) {
  3.         // ... lots of jQuery code ...
  4.         return this;
  5.     },
  6.     // ... other methods ...
  7. });

and possibly changing the return type from void to the class itself, a pointer to it, or reference:

  1. public Builder setFirstName(String value) {
  2.     firstName_ = value;
  3.     return this;
  4. }

It’s true that it may slightly obscure the implementation of fluent class for people unfamiliar with the pattern. But this cost comes with a great benefit of making the usage clearer – which is almost always much more important.

Plus, if you are lucky to program in Python instead, you may just roll out a decorator ;-)

Tags: , , , , , ,
Author: Xion, posted under Programming » Comments Off on Fluent Chaining

Ask for Forgiveness, Not Permission

2013-06-16 6:08

Even though it’s not a part of the Zen of Python, there is a widely accepted principle in Python community that reads:

It’s better to ask for forgiveness rather than permission.

For code, it generally means trying to do something and seeing whether it succeeded, rather than checking if it should succeed and then doing it. The first approach produces something like this:

  1. try:
  2.     print dictionary[key]
  3. except KeyError:
  4.     print "Key not found"

and it’s preferred over the more cautious alternative:

  1. if key in dictionary:
  2.     print dictionary[key]
  3. else:
  4.     print "Key not found"

What I realized recently is that there is much more general level of software development where the exact same principle can be applied. It’s not just about individual pieces of code, or catching exceptions versus checking preconditions. It extends to functions, modules, classes and packages – but more importantly, to the whole process of adding features, extending functionality or even conceiving totally new projects.

Taking a bit simplistic view, this process can be thought of having two extremes. On one end, there is a concept of pure “waterfall”. Every bit of work has to fit into predefined set of phases and no later phase can start before the previous one has completely finished. In this setting, design must be done upfront and all knowledge about the future product has to be gathered before coding starts.
By even this short description, it’s hard to stop thinking about all the hilarious ways the waterfall approach can end badly. Curiously, though, there are still companies that not only follow it but flaunt the fact publicly.

The other end is sometimes called “cowboy coding”, an almost derogatory term for churning out code without regard to pretty much any methodology whatsoever. Like in case of waterfall, it sometimes (very rarely) works, but it’s more so by accident rather than by design. And like pure waterfall, it also doesn’t really exist in nature, as long as more than one programmer is involved.

If we frame the spectrum like this, with the two completely opposite points at the edges, the natural tendency is to search for the middle ground. But if we subscribe to the titular principle of asking for forgiveness rather than permission, the right answer will clearly be shifted towards the “lean” side.
What is permission here? That’s a green light from design, architecture, requirements, UX and similar standpoints. You wouldn’t mind having all these before you start coding, but it is not absolutely crucial. Not having it, you can still do things: code, prototype, explore, and see how things pan out.
Even if you end up ripping it all apart, or maybe even fail to produce anything notable, you will still accrue useful knowledge. Say you have to throw away most of the week’s work because you’ve learned you need to do it differently. So what? With the insight you have gained along the way, it may very well take just a few hours now.

And so thou shalt be forgiven.

Tags: , ,
Author: Xion, posted under Programming » Comments Off on Ask for Forgiveness, Not Permission

Getting Back in Sync with Time

2013-06-08 17:36

Many a hardships are constantly plaguing the hard working IT folks. For example, you may find out that the nearest fridge is out of your favorite drink! But among the so-called First World Problems, there are few that constitute actual, you know, problems – even if you should consider yourself very lucky facing them.

The prime example is this peculiar situation when you’re standing bathed in glaring sunlight, while your body is clearly telling you it’s the middle of the night – or the other way around. I’m talking, of course, about the physiological condition known as jet lag.

It’s pretty stubborn beast, too. There isn’t really a way to avoid it, short of reverting to old fashioned and slow means of transport. And you cannot count on having many innate adaptation to deal with it, either. It would require for our savannah ancestors to have been hopping continents in a few hours on regular basis, which – as far as we know – is not something they used to do.

Nevertheless, the symptoms of jet lag and their severity may vary greatly by person, so most of the advice about dealing with it will not necessarily work for everyone. But among the dubious statements you can find around the Internet, there are also some solid facts here and there.

Flying sucks

Although it’s not technically the cause of jet lag, spending many long hours in closed, cramped, crowded space (also known as “taking a flight”) is certainly a factor that could make its symptoms worse. To reduce that impact, there are few things you can do.

Drink

The air in aircraft’s cabin is typically very dry. In such an environment, you will lose body water faster than on the ground and eventually experience dehydration. I suspect this is also the reason why many people feel the jet lag as a condition similar to hangover.

The solution is, obviously, to drink more. You should never refuse a cup of water whenever the flight attendant offers you one, and you may actually want to actively bug them for even more. This isn’t likely to win you friends but it’s totally worth it, and also conveniently coincides with the next point.

Move

While on the plane, your options to move around are naturally quite limited. It’s never a bad idea, however, to get up, take a few steps and do some stretching. But what’s more important is to actually move around way before stepping on board.

As you probably know very well, the average airliner has a hermetically sealed cabin that keeps the air inside of it at much higher pressure than the surrounding atmosphere it soars through. Unfortunately, the pressure cannot be kept too high, lest the strain on fuselage’s integrity would be too severe and risk implosion. As a result, the density of air (and thus oxygen) in the cabin is usually comparable to that of about 2 kilometers above the sea level.

Unless you live at least that high up and are used to reduced oxygen pressure, you may experience some adverse effects which are curiously similar to the effects of jet lag. Though moving into some elevated area to make your breathing and circulation more efficient is certainly an option, the less radical way is simply to exercise regularly to achieve a comparable effect.

Sleep (probably)

This is hint is a bit more controversial, as some people will recommend staying up for the whole travel. Personally I envy those who are in the position to even consider this as an option. But even then, getting into the more relaxed state by closing your eyes works as acceptable substitute should you choose to do so.

Principles of time travel

The practical effect of moving rapidly to a far away time zone is to make your “day” artificially shorter or longer. Coping with that change therefore requires a temporary adjustment period with altered sleep pattern. To put it simply, you will need to either sleep when you normally don’t, or stay awake when you normally do.

While this is really a matter of your typical habits, I’d wager that for the average reader – who is likely no stranger to coding sessions that drag well into the night – the latter path would be the one of less resistance. Note, however, that especially on eastward flights the total duration of “daytime” may exceed 30 or more hours. Taking a nap while still on the plane would then serve to cushion the blow of having the “evening” moved well past the normal time.

Tags: , , ,
Author: Xion, posted under Life, Science » 4 comments

Implication as an Operator

2013-06-02 18:28

A vast majority of code is dealing with logical conditions by using three dedicated operators: not (negation), and (conjunction), or (alternative). These are often written as !, && and ||, respectively, in C-like programming languages.

In principle, this is sufficient. Coupled with true and false, it’s enough to encode any boolean function of zero, one or two arguments. But language designers didn’t seem to be concerned with minimalism here, because it’s possible to replace those three operators with just one of the following binary functions:

  1. nand(x, y) = not (x and y)
  2. nor(x, y) = not (x or y)

If you can’t immediately see how, start with deriving negation first.
So we already have some redundancy for the sake of readability. While it’s surely a bad idea to try and incorporate all 22 before mentioned functions, isn’t there at least few others that would make sense as operators on their own?

I can probably think of one: the material implication (p \to q). It may seem like a weird choice at first, but there are certain common scenarios where such operator would make things more explicit.
Imagine for a second that some mainstream language (like Java) has been enhanced with operator => that acts as implication. Here’s one example of its straightforward usage:

  1. public class NameMatcher {
  2.     @Nullable private String firstName_;
  3.     @Nullable private String lastName_;
  4.  
  5.     public NameMatcher(@Nullable String firstName,
  6.                        @Nullable String lastName) {
  7.         firstName_ = firstName;
  8.         lastName_ = lastName;
  9.     }
  10.  
  11.     public boolean matches(String firstName, String lastName) {
  12.         return firstNameMatches(firstName) && lastNameMatches(lastName);
  13.     }
  14.  
  15.     private boolean firstNameMatches(String firstName) {
  16.         return matchFirstName() => firstName_.equals(firstName);
  17.     }
  18.     private boolean matchFirstName() {
  19.         return firstName_ != null;
  20.     }
  21.  
  22.     private boolean lastNameMatches(String lastName) {
  23.         return matchLastName() => lastName_.equals(lastName);
  24.     }
  25.     private boolean matchLastName() {
  26.         return lastName_ != null;
  27.     }
  28. }

Many situations involving “optionals” could take advantage of logical implication as an operator. Also note how in this case, the alternatives do not look very appealing at all. One could use an if statement to produce equivalent construct:

  1. private boolean firstNameMatches(String firstName) {
  2.     if (matchFirstName()) {
  3.         return firstName_.equals(firstName);
  4.     }
  5.     return true;
  6. }

but this makes a trivial one-liner suddenly look quite involved. We could also expand the implication using the equivalence law p \to q \equiv \neg p \lor q:

  1. private boolean matchFirstName(String firstName) {
  2.     return !matchFirstName() || firstName_.equals(firstName);
  3. }

Reader would then have to perform the opposite transformation anyway, in order to restore the real meaning hidden behind the non-obvious ! and || operators. Finally, we could be a little more creative:

  1. private boolean firstNameMatches(String firstName) {
  2.     return matchFirstName() ? firstName_.equals(firstName) : true;
  3. }

and capture the intent almost perfectly… At least until along comes someone clever and “simplifies” the expression into the not-a-or-b form presented above.

Does any language actually have the implication operator? Not surprisingly, the answer is yes – but it’s most likely a language you wouldn’t want to code in. Older and scripting versions of Visual Basic had the Imp operator, intended to evaluate the logical connective p \to q.
Besides provoking a few chuckles with its hilarious name, its usefulness was limited by the fact that it wasn’t short-circuiting. Both arguments were always evaluated, even if the first one turned out false. You may notice that in our NameMatcher example, such a behavior would produce NullPointerException when one of the names is null. This is also the reason why implication implemented as a function:

  1. bool implies(bool p, bool q) {
  2.     return !p || q;
  3. }

would not work in most languages, for the arguments are all evaluated before executing function’s code.

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


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