Friday, December 17, 2010
Android fragmentation
Supporting the same app on multiple platforms just sucks. It's the argument that's always brought up in discussions on PC vs. console gaming as the reason why "the PC as a platform is dying". Whether or not that's true (it isn't), the point has merit. Develop for an XBox or an iPhone and you know exactly what hardware and software will run your application. Develop for PC or Android and there's always some amount of praying involved.
I've been tearing my hair out, banging my head against the wall (or whatever other violent metaphor might fit) because the Android Gallery app, which is part of the system, behaves differently when called from my application on Samsung phones than on every other phone. I strongly suspect that the reason lies nestled somewhere deep inside the custom crap Samsung has layered on top of basic Android.
Samsung isn't alone, of course. Motorola does it and I know there are others. Because of Android's open nature these companies have tried to differentiate their products by adding and changing and tweaking. And the result is that on some phones my app just doesn't work. Rather, Android doesn't work, and the perception is that it's my fault.
And of course, I have no Samsung phone to test with. I have been unable to find an emulator for any Samsung phone. What to do? Currently the answer is "put a statement in the description telling Samsung owners not to bother". And that sucks.
An interesting link somewhat related to the topic: Osmos
Wednesday, September 22, 2010
Oracle Shmoracle: Gosling tells all.
Making his point about the “creepiness,” not only with Ellison but with Oracle’s power structure, Gosling said he sparked a notion to try to improve morale amongst the Sun faithful who endured the Oracle acquisition. He said the company decided to rent out the Great America amusement park in Santa Clara, Calif., and allow the Sun folks to have a day of fun. Scott McNealy and Sun CEO Jonathan Schwartz signed off on the project that came in well under budget and all systems were go, Gosling said. Except a few days before the event was to occur, Oracle Co-President Safra Catz got wind of it and put the kibosh on the thing.
“Safra found out and had a fit,” Gosling said. “The word came down that Oracle does not do employee appreciation events. So she forced the thing to be cancelled. But they didn’t save any money because the money had been spent – so we ended up giving the tickets to charities. We were forced to give it up because it wasn’t the ‘Oracle Way.’ On the other hand, Oracle sponsors this sailboat for about $200 million.”
I don't like their database, I don't like their litigiousness, and I apparently wouldn't like working for them. It sounds like corporate hell. And now they have Java, with which I make my livelihood. Bah.
However:
Gosling said he has no concerns about Java’s fate under Oracle.
“I’m actually not very concerned about Java at Oracle, because Java’s really acquired a life of its own,” Gosling said. “There’s only so much damage Oracle can do, because so much of their business depends on Java. It’s in their best interest to treat it well.”
That's good news, I guess.
Tuesday, June 29, 2010
Static vs. dynamic
For the last couple of years I’ve heard the argument proffered by certain touring programming didacts (and perhaps the occasional narpet) that dynamically-typed languages are the future. For a while now static typing is on the outs in certain segments of programming high society--segments which also, not coincidentally, seem to worship at the feet of all things “unit testing”.
I never quite bought it, but couldn’t articulate why. Well, today I was reading Programming in Scala and found a paragraph that rang true:
The argument goes that since such type systems can only detect simple errors, whereas unit tests provide more extensive coverage, why bother with static types at all? We believe that these arguments miss the point. Although a static type system certainly cannot replace unit testing, it can reduce the number of unit tests needed by taking care of some properties that would otherwise need to be tested. Likewise, unit testing can not replace static typing. After all, as Edsger Dijkstra said, testing can only prove the presence of errors, never their absence. So the guarantees that static typing gives may be simple, but they are real guarantees of a form no amount of testing can deliver.
It makes sense. I’ve had a go at programming a complex system in a dynamic language (Ruby), and while I won’t claim my testing was perfect, I wrestled that the kinds of problems this paragraph is talking about. And I would have wrestled with them with better test coverage too. For instance, I find it very useful to get something out of an object and be able to query it (perhaps with an intelligent editor) for the methods I can call on it. With dynamic typing, once my data structures get complex I start to lose the ability to hold in my brain exactly what properties I can call on the things I get by calling properties on other things I have. This isn’t something testing will solve, because it’s a programming-time failure.
Maybe I’ve become lazy and too reliant on code completion tools. If that’s the case, I make no apologies for it. I want my static types! For this and other reasons, Scala is looking pretty attractive.
Monday, April 5, 2010
The Brute Force Programmer Commandments
- I say unto you, this is the first and greatest of the commandments: figure out what to do, and do it until it’s done. Don’t mess around with frameworks, or methods, or events, or hooks, or closures, or “levels of abstraction”, or other such frivolity. If 3000 lines are required to read that file, translate its values, put them in your ArrayList, print the ArrayList, open the database and store its size there and then return its 19th element...well then 3000 lines your monolithic method shall be.
- Verily, art thou not sure something thou needest to use is set up? Set it up again. You know, just to be safe. We might have a valid user, or we might not, so set it up again and you’ll know for sure! You could go examine the other guy’s code to find out what he intends for the program state at this point, but he’s probably as clueless as you and therefore must not be trusted! For your purposes, unknown == uninitialized!
- Is thy variable of a nullable type? Always check it for null before you do anything with it, regardless of where it got its value (even if it was assigned two lines above). Strange and mysterious things go on inside computers; who are you to say that the computer hasn’t suddenly decided to collect your object?
- If thou be coding along down a tunnel, keep thou focused on the light at the end. Don’t get distracted! If something seems like it could go wrong with code you call, be sure to catch any pesky errors that might arise and suffocate them in a catch block before they can derail you.
- If you’re following Commandment #3 you’ll be checking everything for null, but what do you do if something actually is null? At this point it’s important not to interrupt the flow that is bringing you to that happy place. Return something sensible. For instance if your method is getFinalPrice, and your Product is somehow mysteriously null, go ahead and return zero.
- Behold, local variables are bad, because what if you want to use the value you calculated in them in some other method? Make instance fields! Just remember to stay vigilant in your observance of Commandment #2 and keep those fields constantly initialized.
- Instance fields are useless should some other class suddenly want to use them if you just make them private. Every one needs a setter and getter!
- Spelling? Duh. Compilers can’t read English. Whitespace between operators? A waste of keystrokes. Youcanreadthisjustfinecantyou? The same applies to whitespace between blocks. A Bad Programmer makes thousands of lines of code by repetition, not by cheap whitespace.
- If thou be compelled to use local variables, always declare them at the top of your function, even if you don’t use them until the bottom. It’s a matter of principle! Then if you decide you need to use your variable higher up, you’ve saved precious seconds...
- Store everything collection of things thou mayest need in an ArrayList. Then when you need one of the items, iterate through the list until you find it. Don’t use HashSet because that can’t be iterated with an old-style for loop. Don’t use List because, what is that anyway? Use ArrayList.
- Do everything you can to avoid allocating every object. Seriously, you’ll be able to shave that execution time! It’s just that important. Don’t pass around empty collections, pass around null and check for it everywhere. You’ll save milliseconds!
- Thou shalt not covet thy neighbor’s constant. Make your own constant in your own constant file! Your neighbor’s public static final String THIRTY_SIX = “36” is his own and who knows if it will change. You’d better make one for yourself.
Monday, March 29, 2010
A retrospective from the bottom of the waterfall
This is a nasty misuse of the entity manager, so nasty it's almost sinful. As far as I am aware there should never be any need to manually clear it like that. I'm thinking one of those uses probably causes this error, and even if it doesn't I'm sure we're giving ourselves a performance hit by doing it so often.
One particularly egregious example is in MaterialListPriceRltnpBean.saveMaterialListPriceRltnp(). This method is a poster child for all-around shoddy programming (observe, for instance, that it can't decide whether it should begin or end the conversation), but in particular I'd like to show you this bull-in-a-china-shop snippet of code:
materialListPriceRltnpHome.refreshInstance(); materialListPriceRltnpHome.getEntityManager().clear(); materialListPriceRltnpHome.getEntityManager().find(MaterialListPriceRltnp.class, materialListPriceRltnpHome.getInstance().getMaterialPriceListPriceId()); materialSalesOrgRltnpHome.setInstance(materialListPriceRltnpHome.getInstance().getMaterialSalesOrgRltnp()); materialListPriceRltnpHome.refreshInstance();
If you look at that and mutter dejectedly, then you're not alone. This is the code of a man of little nuance, a man who really just wanted his entity but was clueless on how to properly go about getting it. We have code like this all over our application. It's really no wonder our house is falling down around us when we've built it with stinking, rotten wood. All through the app we have code that just sets out to do what it needs to do in the most direct way with no thought for the bigger picture, trampling everything in its path.
How much time have I wasted today alone because someone out there couldn't take the time to learn the proper way to use the tools they were given? Yet supposedly, hiring an army of junior contractors was the only way this project could have been built. Sure, we all make mistakes as we learn, and I do recognize that they feel the same pressure to JUST GET IT DONE OMG WE'RE RUNNING OUT OF TIME that I do and therefore cut corners, as I have done. I also recognize that we didn't give them the constant guidance they needed, but then again I don't think it would have been possible for the small number of us, even reviewing code ten hours a day for the last year, to quell the relentless influx of crap.
I firmly believe that we went about many things wrong on this project, and I know that some of them were the result of laziness or other faults on my part. I do not excuse myself for that. Yet I feel like a drop in the pond; without the good and bad I contributed, the project would still be ailing, because chief among our mistakes was the first one that was made. The model and methodology we chose are just fundamentally, seriously broken. In brazen defiance of common wisdom about the mythicality of the notorious man-month, we finally stopped the hollow overtures to "agile methodology" and openly abandoned it.
It's often said you can't make nine women have a baby in one month. Well, we skipped the nine women altogether and tried to convince 280 women to have a baby in one day. The baby that resulted doesn't seem to happy to have been saddled with the task of existence.
If I have to work any more weekends, I might just start to agree with him.