Seiter's Blog

Mind of the machine

Subscribe to RSS feed

Sticky post

About This Blog

,

This blog is a collection of thoughts and ideas which belong expressly to me, Kevin Seiter. Subject matter ranges from martial arts to poetry, music, physics, my personal life, the state of mankind and of course, software. Enjoy your stay.

Simple Software?

, , ,

It was about 50 degrees outside and breezy in Half Moon Bay, California when I overheard three people discussing robots over lunch.

"So we'll buy the robot for about 50k, then we'll need about 20k more for setup and configuration. That covers pretty much everything except software, which will cost infinity."

They all laughed and one of them, who looked like the guy who paid the bills, rolled his eyes and nodded as if this joke weren't all that far from the truth.

And of course, it isn't. I've written about software for many years now with varying degrees of accuracy. As I've gotten older and experienced more projects, it has become entirely evident that software has a lot of big problems. There are many paradigms out there which promise all kinds of benefits, some of which can be realized. Unfortunately at the end of the day, complex systems are complex. And while that doesn't sound like much, it's altogether meaningful when architects around the world fall prey to silver bullet solutions, shortcuts and other methodologies that often cause more harm than good or lead customers to unreasonable expectations about results.

So what are we to do about this? How can we bring "infinity" to something more reasonable? Here are my suggestions, which are the product of experience and of nothing else.

1. Complex systems are complex: The first mistake any architect can make is to assume he/she fully understands any complex system. I'm not talking about Hello World, or your senior project. I'm talking about multi-component systems. I'm talking about moving parts and integrated systems. Many architects will go up to a white board and draw a bunch of boxes which correspond to subsystems. Since they can see all of the boxes, they assume they understand the system as a whole. I walk up to the board and say, "Draw the lines." Please draw the lines between systems and while you're at it, explain how every line works. And while you're at that, tell me what happens to the system when a line doesn't work as expected. Tell me what happens when 75% through the project, someone draws a new line. Great architects not only recognize that they don't fully understand the complex system, they embrace it. And in this way, they learn to prepare for the unknown.

2. Hire great engineers: Time after time, this is the moral of the story. Again and again, this single factor can determine the success or failure of major components of a system. A good engineer is not one with an incredibly lengthy title. A good engineer is not the hot-off-the-press graduate and it's not the guy with 15 years of experience. A great engineer only concerns himself with the task of solving problems and if he/she has any of the above as well, fantastic. When you interview your potential engineers, ask them to describe something they are proud about having done. "Completed XYZ project" and "Met XYZ deadline" are fine answers but they aren't great answers. "I figured out how to integrate a 15 year old cold-fusion app with a modern web-service using SOAP and a few hundred lines of code I wrote." Bingo.

3. Don't blame your customer: Isn't it easy to blame the customer? A couple useless words fly out of your mouth and you feel better about the fact that you're changing something about your system yet again. Unfortunately, this does nothing to help solve the problem. Customer problems are complex and it would take me ten pages to talk about them in their entirety. I'm also completely unqualified to do so. What I can say is that I've seen this mentality in many organizations and in many engineers. I've seen it in project managers and I've seen it in myself. The truth is, this mentality does nothing to help you accomplish your goal. There are entire books devoted to managing customer expectations and project managers tend to be better at this than engineers do. The best thing you can do as an engineer is to take changes in stride and try to engineer your software to be flexible. Requirements are driven by customers and customers are human. Accept this fact and you'll find yourself in a much happier, healthier engineering state. And your customer will notice.

Related: To Engineer or Not to Engineer

Steve Jobs, 1955-2011

, , ,

Steve Jobs has passed away. Love him or hate him, he changed our world.

Rest in peace.

http://www.apple.com/stevejobs/
http://en.wikipedia.org/wiki/Steve_jobs

Clojure!

, , , ...

Some people were surprised to know that I love Clojure apparently. Take a look at my quick sort and compare it to my python and java variant and it will become obvious why this language rocks socks.

(defn quicksort [list]
  (if (< (count list) 2) list ;if the list has 0 or 1 items, return
    (let [
          pivot (first list) ; our pivot will be the first item
          rl (rest list) ; compare against everything else
          lt #(< % pivot) ; our less than predicate
          gte #(>= % pivot)] ; our greater than equal predicate
    (lazy-cat
      (quicksort (filter lt rl)) ; recurse on filtered less
      [pivot]
      (quicksort (filter gte rl)) ; recurse on filtered greater than equal
    ))))

Make sure we give this bad boy a quick test:

(def mylist (shuffle (range 1 25))) ; make some shufled list of items
(println mylist) ; take a look before sorting
(time (quicksort mylist)) ; time our three runs
(time (quicksort mylist)) ; the first should take the longest
(time (quicksort mylist)) ; magic!

And the results, of course:

[1 2 13 20 19 21 3 22 17 14 16 7 18 10 11 5 12 4 6 8 15 24 9 23]
"Elapsed time: 1.975864 msecs"
"Elapsed time: 0.109321 msecs"
"Elapsed time: 0.107011 msecs"
(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24)

Java Purity and Version 7

, , , ...

With Java 7 coming out in just a hair over two weeks, I thought I'd take some time to look into the language features that were being added. The main items of interest from a language perspective are:

  1. Strings in switch statements
  2. Type inference for generics (Diamond)
  3. Underscores in numbers
  4. Try with resources

Strings in switch statements is fine and arguably should have been in Java a long time ago. You can now:

    public static void switchOnString( String string )
    {
        switch( string )
        {
            case "kevin":
                System.out.println( "In Kevin" );
                // fall through
            case "rob":
                System.out.println( "In Rob" );
                break;
            default:
                System.out.println( "In Default" );
        }
    }

Type inference for generics is a pretty-print enhancement. It makes otherwise verbose generics half as much so.

// before
Map<Integer,String> myMap = new HashMap<Integer,String>();

// after
Map<Integer,String> myMap = new HashMap<>();

Unfortunately, there is no support for initializing using Diamond when the types have to be inferred.

// Diamond lets us do this cleanly
Map<Integer,Map<Integer,String>> myMap = new HashMap<>();

// sadly, we can't do this, the new HashMap has to be fully qualified
myMap.put(new Integer(5), new HashMap<>());

Underscores in numbers is another aesthetic change, allowing erasure of underscores from numbers so that formatting can exist in the code.

long phoneNumber = 555_555_1212L;
double someCash = 12_526_123.45;

Finally, the try-with-resources. Now this one is actually something interesting. It basically allows the programmer to delegate the responsibility of closing resources to Java. Closing resources has always been kind of a pain, requiring try blocks inside finally blocks and so forth. Here's the flavor of the new syntax.

try(
   BufferedReader br = new BufferedReader(new FileReader(new File(fileName)))
){
// do something
}
catch(Exception ex)
{
// catch some exception as a consequence of doing something
}

Any time you add a language enhancement like this, however, you obscure some of the purity of the language. You lose a bit of the "what you see is what you get" feel. For example, if you declare more than one resource in the try, in what order are they processed? Let's find out. We'll build a quick object that conforms to the new AutoCloseable interface.

public class MyAutoCloseable implements AutoCloseable
{
    private String name;
    
    public MyAutoCloseable( String name )
    {
        this.name = name;
    }
    
    public void close()
    {
        System.out.println( "Closing:" + name );
    }
}

Now let's write a trivial case to test the ordering.

    try( 
        MyAutoCloseable mac1 = new MyAutoCloseable( "1" );
        MyAutoCloseable mac2 = new MyAutoCloseable( "2" );
        MyAutoCloseable mac3 = new MyAutoCloseable( "3" );
    )
        {
            System.out.println( "Do something..." );
        }
        catch( Exception ex )
        {
            System.out.println( "Exception:" + ex.getMessage() );
        }

This results in predictable, stack based resolution of the resources.

Do something...
Closing:3
Closing:2
Closing:1

But what if one of these close operations excepts? Will it continue to properly close the other two resources? If so, what if two of the closes except? Will you be able to see both exceptions? It's simple to find out by modifying our class.

public void close()
    {
        System.out.println( "Closing:" + name );
        if( name.equals("2") ) throw new NullPointerException("Closing resource two is exploding!");
        if( name.equals("3") ) throw new NullPointerException("Closing resource three is exploding!");
    }

Running this new condition results in very interesting output indeed.

Do something...
Closing:3
Closing:2
Closing:1
Exception:Closing resource three is exploding!

So the good news is that java is smart enough to make sure the resources have close() invoked regardless of whether or not other resources fail. The bad news is that you can lose exception information. The stack tied with this exception doesn't contain the second exception in the tree either. (As it shouldn't) This could actually happen with the old syntax as well but this syntax obfuscates the issue.

Moral of the story, new language features are great. Use them to your advantage as much as possible. But never forget that your responsibility as a competent developer is not only to make things work but to understand how they work.

Models and The Scientific Method

, ,

When we observe the world, we do so via a model generated by our minds. Our senses absorb data in various forms and pass that information on to our brain, which then processes this information and organizes it in some meaningful way. The concept of a mental model is not a new one. The idea that there is a disconnect between what we sense and what really exists has been around for ages. In Steven Hawking's new book "The Grand Design", he talks about these models and what they mean for Scientific Theory, which brings me to the subject of this post, which is somewhat different from the subjects Steven describes in said book.

The Scientific Method is based on the notion that one can perform observations to prove or disprove a concept. This notion is rooted in the belief that there is a level of purity involved in the process of measurement that is not involved in other forms of inference. The implication is, of course, that observation is the highest form of posit validation. The idea of a model doesn't apply strictly to human observation either, rather, even a device that performs a measurement does so with some set of assumptions. In that case, these assumptions form the foundation of the model from which measurements are made.



But observation only gets us so far. In fact, when you apply this paradigm to electrons, for example, you end up getting some very strange results. The Heisenberg Uncertainty Principle, for example, states that as one increases ones certainty with respect to the position of a particle, one decreases ones certainty with respect to the momentum of the particle. This principle is manifest entirely in the process of measurement. I'm willing to argue that this principle arises out of the application of a classical process (The Scientific Method) to a non-classical (or quantum, if you'd like) concept. (Particles)

Another outcome of this line of thought is demonstrated by a thought experiment called Schrödinger's cat. The result of this thought experiment is that one must accept that at a given time prior to observation of the state of the cat, it is both alive and dead. Statistics can be built around this that properly predict the results of experiments of this sort. These statistics are resoundingly proven to be accurate. But is this really an accurate picture of the universe?



In order to determine the answer to that question, we are left with the tools provided by The Scientific Method. But these tools all require us to perform a measurement. I'm willing to argue that this is the real problem with the current state of physics. Physicists around the world today are struggling to find a "Theory of Everything", a unified theory of physics. I argue that they are looking in the wrong places. The problems that arise when trying to unify Quantum Theory with Relative Theory are caused by the fact that The Scientific Method is a process formed within the classical model of the universe.

So, is there another process we can use to verify posits about the nature of reality which is framed in a non-classical model? Can we determine the laws of nature without using the process of observation and measurement? That is, in my opinion, what the real question on everyone's mind should be.

Layered Functional Interpretation

, ,

Let's say for a moment you have a simple set of functions which all accept similar arguments and affect them in fundamentally similar ways. Take, for example, the following functions:

function applyEarth(int damage,Object target)
{target.life.interpretDamage(damage, DamageType.EARTH);}

function applyFire(int damage,Object target)
{target.life.interpretDamage(damage, DamageType.FIRE);}

function applyWater(int damage,Object target)
{target.life.interpretDamage(damage, DamageType.WATER);}

Let's go on to say that our Object target is going to be affected by three invocations of any of these three functions. Your task is to write a interpreter that will determine the optimal invocations for applying these functions. In this scenario, any of the combinations will be as effective as the others. Simple enough. (Fire,Fire,Fire, for example, is equivalent to Earth,Earth,Earth and Earth,Fire,Water)

Now let's say that our Object target has a certain set of properties:

Object target{EARTH_RESIST=5;FIRE_RESIST=4;WATER_RESIST=3;}

These properties affect the amount of damage target receives when it's life total interprets damage in obvious ways. (Earth resist lowers the effective amount of earth damage, for example but has no affect on water damage)

Now it is obvious the there is a clearly optimal invocation layering. (Water,Water,Water) In this particular scenario, your interpreter is fairly simple because it can quickly determine every set of invocations as well as every resultant based on the Object's properties. Unfortunately, this strategy quickly falls apart.

What happens when you Object has 500 properties? (Linear scale problem) What if you have 500 invocations? (Linear scale problem) Or worse, what if your object has a property that says, every time I'm hit with fire damage, my earth resist decreases. (Exponential scale problem) The fact of the matter is that any brute-force effort here fails sort of miserably. What we can do, however, is build classification sets.

A classification set is simply a way of saying cause and effect. A classification set can have any size and as the size of these sets increases, the computational requirement also increases. (Exponentially) Here's an example of the classification sets for our original scenario.

{Fire->(Damage-Fire Resist)}
{Earth->(Damage-Earth Resist)}
{Water->(Damage-Water Resist)}
{Fire->(Damage-Fire Resist),Fire->(Damage-Fire Resist)}
{Fire->(Damage-Fire Resist),Earth->(Damage-Earth Resist)}
{Fire->(Damage-Fire Resist),Water->(Damage-Water Resist)}
{Earth->(Damage-Earth Resist),Earth->(Damage-Earth Resist)}
...

Using classification sets you can group certain types of properties together and then use brute-force on the classifications instead of the properties themselves. This minimizes the computational requirement but diminishes the efficacy of the interpreter. The fact of the matter is that as you add fundamentally different properties to a system, you significantly increase the complexity of the interpretation.

The moral of the story is that the next time you are playing WoW and you think to yourself, "Why is it that I can only have 12 buffs at a time?" you will now know why. You will also know why even though there may be hundreds of spells and abilities, they all affect targets in fundamentally similar ways. (50 different spells that do fire damage, for example, can be examined as a single classification set)

The INCREDIBLE Review

, , , ...

It's thin, sleek and powerful. But is it really Incredible?

Let me start by saying that I am a lover of all things electronic. I've been scoffed at for the ownership of a ZUNE and I've been scoffed at for the ownership of an iTouch. But this morning at 7AM, I picked up one of the first HTC Droid INCREDIBLE handsets from the Verizon Wireless store in town and I doubt I'll get scoffed at for carrying this piece of fine art around. But 12 hours in, the honeymoon stage is already over and it is obvious that while Google and HTC have done an excellent job, there is still some work to be done.



If you don't know already, the HTC Incredible is the latest in a slew of super-powered Android phones to hit the market. It sports a 1GHZ Snapdragon processor, 8GB of internal memory, a ridiculously vibrant touch-screen and a whopping 8 megapixel camera. It comes with Android 2.1 and HTC's Sense UI on top to smooth out the rough edges. All of this is railed on Verizon's CDMA network which is arguably the best in the nation.

All of that sounds good on paper but how well does it all come together? The answer is a complex one. The INCREDIBLE has a terrible habit of performing feats of pure phone genius one moment and then doing things in the next that simply don't make sense. This process isn't more evident than in the voice recognition features of Android 2.1.

Press a button, say something like "Papa Johns pizza, Syracuse New York" and viola, the INCREDIBLE gives you exactly what you're looking for. The voice recognition is so good in fact, that I kept increasing the complexity of my verbiage just to see how far I could take it. The software finally failed when I threw, "terrible transvestites titillate triple tempura" at it. In all honesty though, it is without a doubt the best speech recognition software I've ever had the pleasure of using.

Unfortunately, after finding Papa Johns spot on, you have to click no less than five buttons to get directions to said location. It's cumbersome, unnecessary and simply annoying. This is a theme that repeats itself throughout the software. The hardware isn't without it's problems either. Sure the back of the phone looks cool; unfortunately the camera lens is the highest level item on the surface and doesn't come with a lens cap, so any time you set your phone on a surface face-up, the lens rubs against it. Only time will tell if the material is affected by this or if it can stand up to it just fine but it's a simple design flaw nonetheless.



Hardware: The HTC Incredible is simply put, a hardware work of art. It's fast, sleek and put together very well. I'd love to see a lens cap though.

Software: Android + Google Cloud + App Marketplace = Awesome. Better control of the software stack would allow a more seamless user experience though and certain features simply feel clunky. This is contrasted by apps that look beautiful, run great and put other apps of their type on other devices to shame. It is difficult as a user to reconcile these two facts.

Overall: The HTC Incredible is a fantastic phone with a fantastic carrier. While it is hard to find many flaws with it, there are some, just as there are with any device. Users looking for a powerful smart-phone on Big Red have an easy decision to make. Those of you who are less concerned about carrier might want to hold your cash a few months and see what the EVO turns out like as well as other offerings coming out this year from Microsoft, Dell and others. For more detailed reviews, head over to any of the links below.


http://www.engadget.com/2010/04/19/droid-incredible-review/
http://gizmodo.com/5520071/htc-droid-incredible-review-more-like-impressive
http://www.infosyncworld.com/reviews/cell-phones/htc-droid-incredible/10909.html

My Problem with Non-Linearly Complex Divergences

I've been struggling with something I read recently about mapping of gravity divergences using test particles and I'm wondering if any of you have any ideas how it works or even better, can explain why the way I'm understanding it is incomplete or incorrect. To wrap up the problem tersely, let's imagine for a moment we have two particles of mass > 0 in a simple reference frame, as shown:



Now what I read was that you can create a mapping of the gravitational divergences using these so-called "test" particles. You simply imagine them, they have zero mass, and you use them to determine the gravitational effect at that position, which is simply the sum of the gravitational vectors between the test particle and all gravitational objects in the frame. Using a series of these particles, you can map a gravitational field of a system. Take test particle I for example, and this follows:



My problem with this is that the resultant, -IAB, is a vector. Vectors have magnitude. This magnitude creates a resultant acceleration which is based on the mass of the object the vector is applied to. For example, when you jump off a tall building you rush toward the earth but it makes little effort to rush toward you, even though Newton's Laws tell us that the gravitational force on you from the earth is the same as the gravitational force on the earth from you. (They are equal and opposite.) Since this vector is divided by the mass of the object, and we are so very light in comparison to the mass of the earth, we rush toward the earth more than it rushes toward us.

Having said that, our test particle can't be applied to the resultant vector -IAB because it's mass is zero. As the test particle's mass approaches zero, it's velocity approaches infinity.(Note that velocities > c are not allowed!) Also, you can't simply give your test particle mass > 0 because then it will cause an acceleration on A and B which will move them at t = t + 1. This results in a mapped field which does not correctly represent the actual field you are attempting to investigate.

My gut feeling is that the notion of the test particle as a means of creating a gravitational map is flawed. In a minor way, sure (since you can give i an arbitrarily small m > 0 such that the acceleration on A and B is negligible) but flawed nonetheless. It seems to me this is similar to the uncertainty principle, in a way. You can know the masses of the particles in the system (I think?) but you cannot properly map their gravitational field without affecting it in some, however minor, way.

Someone correct me if I'm wrong?

The Good, The Bad and The Ugly of Gaming 2009

The Good

Dragon Age: Origins (PC)

Bioware came out swinging with DAO this year, putting to rest any thoughts that the adventure RPG was dead. After a couple terribly sad failures from other companies like NWN2 from Atari, it was a breath of fresh air to see such a polished, well developed game come out for this genre. Flaws like release date DLC, no multi-player and a defunct editor couldn’t keep this otherwise fantastic game from success in 09.

Demon’s Souls

This is a typical conversation among gamers in the days following the release of Demon’s Souls;
“Dude, have you played Demon’s Souls yet?”
“What the hell is that?”
“It’s a new game from Atlus and it rocks socks.”
“Who the hell is Atlus?”
Yeah, some people probably knew Atlus from Shin Megami, Ogre or Persona but most didn’t. This game hit most gamers like a kick in the face. It was very challenging, terribly unforgiving and absolutely fantastic. The difficulty reminded us all about how gaming in general has shifted over the last few years and single-handedly broke more PS3 controllers than all previous titles combined.

Uncharted 2: Among Thieves

Naughty Dog knew exactly what they were doing when they started work on this masterpiece. They took everything that was amazing in Uncharted 1, polished it, added to it and kicked everything that sucked to the curb. Amazing script and voice acting, fantastic flow of game play elements and a multiplayer mode that holds its own against other games made specifically for that purpose make Uncharted 2 one of the best of 09.



The Bad

Aion: Tower of Eternity

More like “Aion: Grind for Eternity”. I have played MMO’s since EQ and am no stranger to the grind. I was the first L70 on my server back in my WoW days and one of the first MB wizards on Bertox. Even still, a grind for the sake of a grind is just plain terrible. Level 40 hits most gamers like a plate train. Add on to that the relentless botting / RMT / phishing, a terrible first few weeks of release and an absolutely horrendous endgame and what’s left is a pretty game powered by a phenomenal engine (Thanks Crytek) and not much more.

Call of Duty: Modern Warfare 2 (PC)

Fat Activision Exec: “All right, let’s get MW2 on the shelves before Christmas 09”
Senior Game Designer: “We only have 8 hours of single player content and haven’t figured out a solution for dedicated servers for the PC version. We need until March 10 at least”
Fat Activision Exec:”We’ve got this thing and it’s fucking golden. Box it up.”
I assume that’s how the conversation went some time in early 09 when they announced the release date for this steaming pile. If anyone purchased this game for PC, I’m so sorry.

Diablo III Release Date

“Next Few Years” read the slide at the Blizzard conference, and babies around the world started crying. Seriously, I know you guys are busy copying and pasting content from Burning Crusade for your next 15 WoW expansions but with the cash you are generating every month from your 13+ million subscribers, you’d think you could hire a couple more folks to get D3 out the door? Oh wait, you don’t want it to be released until you’ve milked WoW for every possible cent, since D3 will inevitably take market share from WoW and doesn’t generate recurring revenue like WoW does.



The Ugly

Microtransactions and DLC

We all saw it coming when the guys at Bethesda started selling saddle bags for 5 bucks in Oblivion. I had hoped the public outcry against DLC would have stymied its adoption but that proved to be too optimistic. The truth is, DLC and microtransactions will probably become the status-quo within the next couple years. What this will mean for gaming as a whole has yet to be seen. Among the sea of fail that is microtransactions, we’ve seen some glimmers of hope from the paradigm in the form of Free-To-Play options like Dungeons and Dragons: Online but so far that has been the exception, rather than the rule. With terrible omen like Dragon Age: Origins launch date DLC and others, gamers have reason to be concerned.

And we are faced with the hard truths of the proliferation of gaming. As titans like EA and Activision push harder and harder for their 16% margins, it is the gamers that suffer. And unlike the typical voting process, copy/paste titles like MW2 still sell like monsters, reinforcing the concepts of their progenitors. And all we can do, the dedicated few, is mock their paradigms from afar on blogs and forums and hope that the developers of conscience continue to exist and create fun, complete games for a single, fair price.
February 2012
S M T W T F S
January 2012March 2012
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29