Now, I'm working on Facebook apps using OAuth 2.0, and the draft specification says in section 4.2 that JSON is returned when retrieving the access token. However, Facebook's OAuth 2.0 server returns application/x-www-form-urlencoded data. I anticipate things changing without notice, so I'll have to code it flexibly. Of course, it is a draft specification.
As for OAuth 2.0 versus OAuth 1.0, it's a little nicer. Code for computing the signature for OAuth 1.0 is difficult to debug, but, once it's working, it's easy. On the server side, incorrect nonce handling seems like an obvious hole for replay attacks, and OAuth 2.0 is better in that way. Also, unencrypted OAuth 1.0 traffic can still be snooped. Of course, OAuth 2.0 is still subject to traffic analysis. Of course, with Facebook's reputation on privacy, these differences are irrelevant for most Facebook apps, including the ones I'm working on.
Monday, October 25, 2010
Monday, October 18, 2010
After using Guice for a little while, I've started learning how to use it better. I can use @Provides methods to configure objects. I like being able to install() modules for modularity.
For webapps, I can have two web.xml files, one pointing to one configuration, and another pointing to another configuration, such as a test configuration, by specifying the different configuration classes as the listener in web.xml files, where the bindings specify different implementations.
I'm not sure if I like the fluent interface. It's nice for reading the code, but it makes referring to the javadoc more difficult. It also creates a bunch temporary objects, but that isn't really a concern. Guice is supposedly a lot faster than Spring, and the temporary objects probably can be optimized away by escape analysis.
For webapps, I can have two web.xml files, one pointing to one configuration, and another pointing to another configuration, such as a test configuration, by specifying the different configuration classes as the listener in web.xml files, where the bindings specify different implementations.
I'm not sure if I like the fluent interface. It's nice for reading the code, but it makes referring to the javadoc more difficult. It also creates a bunch temporary objects, but that isn't really a concern. Guice is supposedly a lot faster than Spring, and the temporary objects probably can be optimized away by escape analysis.
Monday, October 11, 2010
I've only had a cursory look at Google Guice, but this is my first impression as compared with Spring, which I've used a lot more. Using Spring has actually changed the way I approach writing code.
What I like about Guice is that it is statically type-checked. Spring's xml configuration is like a dynamically typed language, and more errors slip through to later stages.
What I like about Spring is that code doesn't need to be written with any Spring-specific calls or constructs, whereas Guice requires Guice-specific annotations. If I only had to deal with code I've written, it wouldn't matter so much. However, Spring makes it hooking in code from external libraries more convenient.
Also, when using Spring, I like being able to specify every last configurable flag in the xml configuration, and anything that truly needs to be tuned can further be extracted into a properties file. Guice seems to make that level of configuration more inconvenient. Perhaps I am overlooking some mechanism, but it seems inconvenient to have to insert yet another annotation to name yet another string field that I want to configure, rather than just being able to inject beans. Guice seems to encourage having a few, high-level, injected objects, rather than every last configurable value injected.
One nice thing about Guice is that it can inject private fields, while Spring requires a public setter method. This is just a minor thing though, since, while the implementing class may have some public setters, the public interface that it is being injected as won't have those public setters. There is also constructor injection, but that is not convenient when there are many parameters to inject.
What I like about Guice is that it is statically type-checked. Spring's xml configuration is like a dynamically typed language, and more errors slip through to later stages.
What I like about Spring is that code doesn't need to be written with any Spring-specific calls or constructs, whereas Guice requires Guice-specific annotations. If I only had to deal with code I've written, it wouldn't matter so much. However, Spring makes it hooking in code from external libraries more convenient.
Also, when using Spring, I like being able to specify every last configurable flag in the xml configuration, and anything that truly needs to be tuned can further be extracted into a properties file. Guice seems to make that level of configuration more inconvenient. Perhaps I am overlooking some mechanism, but it seems inconvenient to have to insert yet another annotation to name yet another string field that I want to configure, rather than just being able to inject beans. Guice seems to encourage having a few, high-level, injected objects, rather than every last configurable value injected.
One nice thing about Guice is that it can inject private fields, while Spring requires a public setter method. This is just a minor thing though, since, while the implementing class may have some public setters, the public interface that it is being injected as won't have those public setters. There is also constructor injection, but that is not convenient when there are many parameters to inject.
Monday, October 4, 2010
I ran across a bug in an Android app that I was working on that had me throwing the phone to the floor multiple times in frustration. I finally tracked the problem down to SurfaceHolder.Callback.surfaceChanged() being called twice when the phone is held vertically, but only once when the phone is held sideways. Everyone using the app holds the phone sideways when using the app because the text and icons are all sideways. However, I had said to myself, "Screw that. I'm not going to turn the phone sideways just for that." I don't know what the proper way to fix it is, since I don't know why the code is in SurfaceHolder.Callback.surfaceChanged(), and the person who wrote it had just moved on to another company (Google, actually) a week earlier.
Monday, September 27, 2010
Here's a bug that I recently came across. I didn't figure it out, and it wasn't code I wrote, but it is an example of gratuitously bad code.
Originally, I had written some code for a quick-and-dirty demo that went something like:
where readPacket() read the appropriate number of bytes into the buffer depending on the packet type. Something like:
Somewhere along the line, in a change in source control that was something along the lines of "update to the latest protocol", there were a number of changes, including gratuitously changing the code from something like the above, to something like:
and readPacket() was changed to
which all would have worked fine, even though it was a stupid and gratuitous change, except that there was another place that called readPacket(), but ignored the packet. So, if that other place called readPacket() and got TYPE1, the packet wouldn't be fully read, and subsequent calls to readPacket() would return garbage. I don't know what the thinking was behind changing the code like that.
Originally, I had written some code for a quick-and-dirty demo that went something like:
packetType = readPacket(input, buffer);
switch (packetType) {
case TYPE1: parseType1(buffer); break;
case TYPE2: parseType2(buffer); break;
...
}
where readPacket() read the appropriate number of bytes into the buffer depending on the packet type. Something like:
packetType = input.read();
if (packetType == TYPE1) {
read some stuff into buffer;
} else {
count = input.read();
read count bytes into buffer;
}
return packetType;
Somewhere along the line, in a change in source control that was something along the lines of "update to the latest protocol", there were a number of changes, including gratuitously changing the code from something like the above, to something like:
packetType = readPacket(input, buffer);
switch (packetType) {
case TYPE1: read more stuff from input; break;
case TYPE2: parseType2(buffer); break;
...
}
and readPacket() was changed to
packetType = input.read();
if (packetType == TYPE1) {
return packetType;
} else {
count = input.read();
read count bytes into buffer;
}
return packetType;
which all would have worked fine, even though it was a stupid and gratuitous change, except that there was another place that called readPacket(), but ignored the packet. So, if that other place called readPacket() and got TYPE1, the packet wouldn't be fully read, and subsequent calls to readPacket() would return garbage. I don't know what the thinking was behind changing the code like that.
Monday, September 20, 2010
One component of this demo that I'm working on is a server in C++. The guy who did the work on it was laid off 5 months ago, and now I have to add crap to it. Most of it was 3rd-party code. I don't know what changes have been made to it, since it was checked into source control in one big chunk 9 months ago. However, there is one directory that has our specific configuration files and build and startup and shutdown scripts.
I found the build, startup, and shutdown scripts kind of annoying. They all assumed that the scripts would be run from the directory that the script were in, which I don't like to do. I prefer running /absolute/path/to/the/script, rather than cd /absolute/path/to/the, then ./script. So I added cd `dirname $0` to the top of all the scripts. Another goofy thing in the scripts were the use of pushd somedirectory >/dev/null, and then popd >/dev/null. Personally, I use directory stacks interactively all the time, and often have 3 or 4 directories that I switch between, but, for the script, cd somedirectory, then cd .. would work just as well.
As for the C++ server, I had to add a feature, which I did. And it worked some of the time, but mysteriously didn't work some of the time. There was a logging framework that I tried to use, and I spent a day trying to use it. When I tried making a new logger class, and tried enabling it, the server crashed. Finally, I just hacked in some code that fopened a file, and vfprintfed crap directly to it, and figured out that I had added an uninitialized variable to a class, and, depending on what value it had, the feature worked or didn't. So I fixed it by initializing it in the constructor.
I found the build, startup, and shutdown scripts kind of annoying. They all assumed that the scripts would be run from the directory that the script were in, which I don't like to do. I prefer running /absolute/path/to/the/script, rather than cd /absolute/path/to/the, then ./script. So I added cd `dirname $0` to the top of all the scripts. Another goofy thing in the scripts were the use of pushd somedirectory >/dev/null, and then popd >/dev/null. Personally, I use directory stacks interactively all the time, and often have 3 or 4 directories that I switch between, but, for the script, cd somedirectory, then cd .. would work just as well.
As for the C++ server, I had to add a feature, which I did. And it worked some of the time, but mysteriously didn't work some of the time. There was a logging framework that I tried to use, and I spent a day trying to use it. When I tried making a new logger class, and tried enabling it, the server crashed. Finally, I just hacked in some code that fopened a file, and vfprintfed crap directly to it, and figured out that I had added an uninitialized variable to a class, and, depending on what value it had, the feature worked or didn't. So I fixed it by initializing it in the constructor.
Monday, September 13, 2010
There is some demo code at work that's been around for around 10 months, and I've added various features to it from time to time. Also, from time to time, the deployed code has to be put in a "known state" to actually do the demos. A month or two ago, some other guy added a feature, which makes the user interface fancier, so his changes need to be in all the demos, but he never checked anything into source control. Since then, I've added some features, all of them checked in. So now when there is a demo, this guy has to merge my changes into his code and then deploy it on the demo system. Except that what has actually happened is that they go back to the code that he originally deployed over 3 months ago, which doesn't have any the features I've added, which include changes that make the platform more robust. I can't deploy the demo including his features because I don't have his code.
One of these days, I'm going to ask him why he doesn't check his crap in.
I don't understand how some people can work on stuff while rarely interacting source control. I update my source trees often. I update before starting work. I merge in changes periodically during work. I merge in changes when I'm ready to check stuff in. I check stuff in when I'm done working on it.
One of these days, I'm going to ask him why he doesn't check his crap in.
I don't understand how some people can work on stuff while rarely interacting source control. I update my source trees often. I update before starting work. I merge in changes periodically during work. I merge in changes when I'm ready to check stuff in. I check stuff in when I'm done working on it.
Subscribe to:
Posts (Atom)