4 ms·
Out of all the things I know how to do in programming, reducing complexity is probably the one I'm best at. So how do I get a job doing this? Or a series of luc
by Stratoscope 11y ago
Out of all the things I know how to do in programming, reducing complexity is probably the one I'm best at. So how do I get a job doing this? Or a series of lucrative consulting gigs? :-)
I'm pretty sure I'm not as smart as I used to be, and I'm definitely not as smart or productive as some of the younger programmers I've worked with. (Sorry for the ageist remark!)
This may be my secret advantage: I have to keep my code simple enough that even I can understand it.
Here's a fun example that I've seen more than a few times in various forms: four-way navigation, either involving up/down/left/right or north/south/east/west, or both.
In one (somewhat disguised) project it worked like this: the code had several different modules to provide a keyboard interface for geographic navigation, while keeping the geo code separated from the low level details of key codes and events and such.
There was a keyboard manager that mapped keycodes to readable names that were defined in an enum:
switch( keyCode ) {
case 37:
return KEY_LEFT;
case 38:
return KEY_UP;
case 39:
return KEY_RIGHT;
case 40:
return KEY_DOWN;
}
Then an event manager broadcast navigation messages based on the KEY_xxxx codes:
switch( keyEnum ) {
case KEY_LEFT:
BroadcastMessage( 'keyLeft' );
case KEY_RIGHT:
BroadcastMessage( 'keyRight' );
case KEY_UP:
BroadcastMessage( 'keyUp' );
case KEY_DOWN:
BroadcastMessage( 'keyDown' );
}
A navigation manager received these messages and called individual navigation functions:
// Don't forget to reverse the directions here
events.on( 'keyLeft', function() {
moveRight();
});
events.on( 'keyRight', function() {
moveLeft();
});
events.on( 'keyUp', function() {
moveDown();
});
events.on( 'keyDown', function() {
moveUp();
});
These navigation functions panned a map in one compass direction or another:
function moveUp() {
map.pan( maps.DIRECTION_NORTH );
}
function moveDown() {
map.pan( maps.DIRECTION_SOUTH );
}
function moveLeft() {
map.pan( maps.DIRECTION_WEST );
}
function moveRight() {
map.pan( maps.DIRECTION_EAST );
}
Of course most of you reading this can see the problem at a glance: Besides having so many layers of code, how many different names can we give to the same concept? We've got KEY_LEFT, keyLeft, moveLeft, and DIRECTION_WEST that all mean pretty much the same thing!
Imagine if math worked like this: You'd have to have two of every function, one for the positive numbers and another one for negative numbers. And probably four different functions if you are dealing with a complex number!
That of course suggests a solution: use numbers instead of names, +1 for up and -1 for down, ditto for right and left. And pass these numbers on through any of these layers of code so you only need half the functions. If you need to flip directions along the way (like the left arrow key navigating right), just multiply by -1 to reverse it instead of having to make special cases for each direction name.
You might even decide to combine the two axes, so instead of vertical and horizontal, you've got +1 and -1 there too (or 1 and 0, or something that lets you handle both axes with one piece of code). Now you could be down to a quarter of the original code.
Unfortunately, I was brought in on this project near the end to help wrap up a few other tricky problems, and all this navigation code was already set in stone. (And to be fair, working and tested, and who wants to go back and rewrite proven code, even if it is four times the code you need?)
But this would make a pretty good "how would you clean this code up" interview question!
- cactusface 11y agoIt's actually reasonable. Step 1, translate key push. Step 2, broadcast key message. What you're missing is that there's an alternate Step 1, translate joystick hat push (or mouse drag, or whatever). So Step 2 should be broadcast generic up/down/left/right input message. Step 3, translate message into movement. But what you're missing is that dependent on context, there's going to be other things besides movement that those keys do. Step 4, pan the map with N/S/E/W. Again here, you have the flexibility to work with a rotated map. Your code was probably overdesigned for the use case, but I've seen your solution many times, in books and in real life. However, I've also solved this problem by passing around polar coordinates, it's elegant and very flexible but you have to munge some data at the beginning. You can also pass around a simple vector [{-1, 0, 1}, {-1, 0, 1}], which is basically what you describe.
- d23 11y agoHonestly it seems like the many layers of indirection would be a much bigger problem for complexity. It may not be bad in this situation, but it certainly takes more mental effort to comprehend than seeing a corresponding "right", "down" and "up" for every "left".