All timestamps are based on your local time of:

[ « Newer ][ View: List | Cloud | Calendar | Latest comments | Photo albums ][ Older » ]

Software Liability2011-09-23 11:01:31

If you're in the software industry, the contents of this article are something you should definitely think about. I, for one, agree with the main points he makes - I think that for software to get better, developers have to be held liable for the software they produce. Today, software is everywhere, and we rely on it running almost every aspect of our lives. Buggy software can have a disastrous effect, much more so than a collapsed building. As a software developer, I don't like the idea of liability, because it constrains what I can do. As a consumer, though, I love it, because it helps levels the playing field between those in power (software developers) and those without (average users).

If you're a software professional reading this, chances are you graduated from the SE program at UW, which as I'm sure you recall, is PEO-accredited. I encourage you to get the ball rolling on that front, and try to earn a Professional Engineer license. I see it as one of the possible first steps towards fundamentally improving the software industry. I sent in my application a couple of months ago, and plan to take the PPE in December. Finding a mentor and getting the required amount of work experience is going to be harder, since there aren't very many practicing licensed software engineers out there. The sooner you sign up, the sooner you can get licensed, and the sooner you can mentor others in getting their licenses. Exponential growth in licenses for the win! Get started.


Thoughts on Android2011-01-28 01:51:59

While I was initially impressed by Android's architecture and APIs, I am now somewhat less than impressed. I've been spending a lot of time over the last few days trying to add my own AccountAuthenticator and the results haven't been pretty. I followed the docs at first, but that failed miserably. After much investigation I found the SampleSyncAdapter code and figured out what it was doing and replicated that. That helped somewhat - at least I was able to get an account added.

If it was just that API then I wouldn't have a problem with it. But I think there's something underlying the Android implementation that is seriously messed up. There's a lot of cross-process communication going on under the hood, and there's a lot of hoops that the system jumps through when doing the IPC. I don't fully understand the process model in Android, but there's a lot of intricacies with permissions, protections, and hidden IPC calls that seem to be making things much more complicated than they appear.

As an example, at one point I tried calling BluetoothAdapter.getDefaultAdapter() from a helper thread and that died saying it couldn't create a Handler object from that thread because I hadn't called some Poller method. It was pretty absurd since it was trying to invoke the method via IPC and needed the Handler for the callback. But of course, this isn't documented anywhere and I only found out at runtime when it threw the exception. Unless every codepath gets exercised during testing, stuff like this has the potential to blow up apps in production, which is very, very bad.

I'm still having a problem where I call AccountManager.getAuthToken().getResult() from my app, which does get through to my AccountAuthenticator and obtains an auth token, but then that thread of execution just hangs somewhere. It never returns back to the app, and I have no idea why. I did try poking through the relevant AccountManager code but didn't have the time to figure out all the magic and abstraction going on in there. Debugging with Eclipse wasn't much help either since (a) there's no source jar distributed with the emulator and (b) after I got a source jar that somebody made available, it still wouldn't set breakpoints or let me debug that code, and I don't know why.

Another issue I keep running into is the number of different permissions I need to keep adding to my app to do things. I do like the idea of having fine-grained permissions so that the user knows exactly what the app is up to, but some of these permissions don't really map to concepts the user can readily understand. How would you explain to an average user the difference between the MANAGE_ACCOUNTS, AUTHENTICATE_ACCOUNTS, USE_CREDENTIALS and GET_ACCOUNTS permissions? The distinction is confusing enough for developers, let alone users. And not just app developers - the AccountManager.invalidateAuthToken() method documentation claims to allow both MANAGE_ACCOUNTS and USE_CREDENTIALS, but when I try to use with USE_CREDENTIALS it throws an exception. Clearly this stuff is complex for Android contributors too. It's also not clear to me which permissions are propagated when the under-the-hood IPC stuff happens.

Since I'm working against Android 2.1, I'm sure some of this stuff has been addressed in newer versions. And my experiences have been mostly confined to the accounts API, so they may not be representative of the platform as a whole. I also haven't spent a lot of time reading through the developer guide. I did skim it, but who really reads that stuff end-to-end? But I'm still worried because I'm starting to get the feeling that some of the fundamental design decisions behind the Android architecture are turning out to be poor ones.


Random hacking2010-12-27 21:38:23

During the last school term, I was working on two different projects where I realized it would be really handy if I could update cells in a spreadsheet from a script. That step was the one step I had to perform manually in an otherwise fully-scripted chain of commands.

I looked around for existing tools to do this but unfortunately couldn't find any that did quite what I needed. So I grabbed the ODFPY library (closest match for what I wanted), a Python language reference, and my trusty sidekick vim. A few hours later I had my first non-trivial python chunk of code, a module on top of ODFPY to read and write arbitrary blocks of cells from and to an ODF spreadsheet. Also managed to fix an existing ODFPY bug along the way.

I submitted my patch and new module to Søren Roug, the author of ODFPY, and he agreed to include it as one of the contrib modules distributed with the library so others who find it useful can also use it and extend it as they need.

Just another example that shows how open standards (i.e. ODF) and free/open-source software (i.e. ODFPY) empower users.

And speaking of open systems, I really like the design and flexibility of the ContactsContract API in Android. Creating a sync adapter to inject contact information from custom sources is pretty simple and works more or less how I'd expect it to. I just wish the high-level documentation were a bit better; that would have saved me some time. The same goes for the Android Account API - it looks flexible and well-designed but the package-level documentation is kind of hard to follow.


Libgcrypt2010-12-03 01:33:33

This post is about my recent experience in trying to use libgcrypt-1.4.6, although older versions probably exhibit the same behavior. I'm putting this online so that anybody else who runs into the problems might find it useful.

First of all, libgcrypt doesn't do base64 encoding. Even though the header files have base64-related constants, it doesn't do anything with them. Filed as Issue 1303.

Second, libgcrypt doesn't do elliptic curve encryption. It does have ECDSA support, but only for signing and verification. I found the gnupg-ecc project which claims to add full ECC support to GnuPG, but unfortunately it doesn't seem to expose it correctly via libgcrypt. I logged issue #1 on the project asking for clarification but there hasn't been a response yet. In short, I couldn't get ECC encryption/decryption working with libgcrypt, even using gnupg-ecc.

Third, when serializing and de-serializing s-expressions, be careful of the format you use. In particular, given the classic rsa key-gen example "(genkey (rsa (nbits 4:1024)))" you might think that a value of the format <length>:<data> will always be interpreted the same way, where <length> and <data> are both base-10 numbers, and <length> indicates the length of <data>. This is not always true, however - it depends on where the number is being used. In fact, if you look at the src/sexp.c file in libgcrypt, you'll see that the <data> field is read in assuming it's a binary field. It's only later in cipher/pubkey.c that strtoul is called on that field, thus parsing it as a base-10 value. I found this out the hard way after trying to build an RSA public key with an exponent expressed as "(e 5:65537)". The "65537" in that got interpreted as a binary field instead of the base-10 value that I was expecting it to, resulting in a hard-to-track-down bug. The correct approach to doing that is to write "(e #010001#)".


XML2009-05-02 18:15:43

I was thinking about a conversation I had the other day where somebody was considering using XML for marshalling/transferring data between two networked hosts. I felt, and still feel, that using XML for something like that is a poor choice. After thinking about it more, I realized that XML sucks when used in communication protocols, but is still useful when used as a data storage format.

The key difference, I think, is the fact that communication protocols are only used while there are entities communicating. If all of those entities cease to operate, then the protocol is effectively dead and/or useless. The communication protocol, therefore, is transient in nature. With data storage, though, it is the opposite. If you save a file, that file is going to stay around as long as you want it to, even if all the apps used to manipulate that file no longer exist.

This difference means that the data storage format must be self-documenting, whereas the communication protocol does not need to be. If you want to recover the data even after all the manipulating apps are gone, you need to be able to look into the file and figure out what is what without being able to look at any source code - that's what XML is great at. With the communication protocol... who cares? If all the communicating entities are gone, just invent a new protocol and be on your merry.

The other thing XML claims to be good at is extensibility. The claim is that XML is a well-defined, structured format, and it is easy to create schemas and extend files with more tags/attributes as necessary. While that is true, it is not a property specific to XML. Binary formats can be just as extensible as XML; they're just not as human-readable. You can reserve bytes and bake in room for backwards-compatible expansion into any well-designed binary protocol. And in both cases (XML and binary formats) any expansion to the protocol will require updates to the implementations that read/write the protocol, so there's no magical advantage to XML on that respect either.

The advantage with binary protocols is that they're more efficient - both in terms of bandwidth and processing time. A switch(read()) loop will outperform a SAX parser by multiple orders of magnitude, and so they make far more sense to use in a communication protocol. With data formats, you could at least argue that self-documentation is important for data persistence and recovery, and therefore conclude that XML would be a better choice.

I don't recall anybody ever really making the distinction between these two categories in which XML is commonly used. At first XML was new and cool and people used it for everything. Then there was a wave (as with all new technologies) where some people decided XML was no longer cool and denounced it as bloated and useless. Now its use is split between people who think it is awesome and people who disagree, rather than using it where it is appropriate and where it is not. An unfortunate state of affairs indeed.


The definitive guide to whitespace, part 12009-03-10 23:17:14

Part 1: method invocations

The rules

  • Arguments in favor or against any of the options must not be based on subjective viewpoints (e.g. "it looks prettier").
  • Mention of languages that do not follow a C-style syntax is strictly prohibited (to avoid flame wars).

The options

optionA(foo, bar, func(baz));
optionB( foo, bar, func( baz ) );
optionC (foo, bar, func (baz));

The arguments
Option A is the shortest, requiring the least amount of typing, and fastest compilation time.

Options A and B have no whitespace before the opening parenthesis, therefore requiring a shorter search string when looking for instances of the method invocations (i.e. grep "optionA(" instead of grep "optionA (").

Option B is most convenient for manipulation via a tool (such as a naive code preprocessor), since useful tokens can be obtained by splitting the code on whitespace. Option A would return things like "optionA(foo," which are less useful than "optionB(" and "foo," separately.

The conclusion
To be determined once y'all weigh in with additional options and arguments.


[ « Newer ][ View: List | Cloud | Calendar | Latest comments | Photo albums ][ Older » ]

(c) Kartikaya Gupta, 2004-2023. User comments owned by their respective posters. All rights reserved.
You are accessing this website via IPv4. Consider upgrading to IPv6!