Pages

Sunday, December 13, 2015

Welcome to 17 Lines

Hello.  Thank you for visiting.

In this blog, we present the core of particular algorithms. The 17 essential lines of code.

This blog is intended as a library of curated code snippets. It is also a learning resource -- for bootstrapping a new platform or environment. Most of us know that when adopting a new platform or framework, even the most basic operations (hello world, logging, network I/O, error handling, configuration) require substantial time to understand. And then after a while, it dawns that our initial approach wasn't the best, or has limitations we'd have avoided if we'd only known.

More often that not, reference manuals, if they exist, are written for those that are familiar with the platform being used, and its history. Successful platforms and frameworks have substantial code deprecation that isn't obvious. Are we using patterns that are best avoided going forward? Did we copy code from a web search only because it was near the top of the results? How can we get productive with a new platform as quickly as possible using the future facing patterns?

Consider this example, pseudo code for in-order traversal of a binary tree (from Wikipedia):

1:  inorder(node)  
2:   if node == null then return  
3:   inorder(node.left)  
4:   visit(node)  
5:   inorder(node.right)  

Now, here's an actual implementation with all the details and all the reality of more general production code. (from OpenJDK source):

1:  abstract class PrivateEntryIterator<T> implements Iterator<T> {  
2:      Entry<K,V> next;  
3:      Entry<K,V> lastReturned;  
4:      int expectedModCount;  
5:    
6:      PrivateEntryIterator(Entry<K,V> first) {  
7:        expectedModCount = modCount;  
8:        lastReturned = null;  
9:        next = first;  
10:      }  
11:  ...      
12:      final Entry<K,V> nextEntry() {  
13:        Entry<K,V> e = next;  
14:        if (e == null)  
15:          throw new NoSuchElementException();  
16:        if (modCount != expectedModCount)  
17:          throw new ConcurrentModificationException();  
18:        next = successor(e);  
19:        lastReturned = e;  
20:        return e;  
21:      }  
22:  ...  
23:    static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {  
24:      if (t == null)  
25:        return null;  
26:      else if (t.right != null) {  
27:        Entry<K,V> p = t.right;  
28:        while (p.left != null)  
29:          p = p.left;  
30:        return p;  
31:      } else {  
32:        Entry<K,V> p = t.parent;  
33:        Entry<K,V> ch = t;  
34:        while (p != null && ch == p.right) {  
35:          ch = p;  
36:          p = p.parent;  
37:        }  
38:        return p;  
39:      }  
40:    }  

Both of the above are clear. One is more concise. One is more realistic. Why is the Java implementation using a parent pointer instead of a recursive stack? Is it important enough that I should do something similar in my new implementation of tree walk? Or is this implementation dependent noise?

Of course, many common computer algorithms are exhaustively explained. There are entire courses on algorithms. The well designed syllabus covers why, how, time-space tradeoffs, history, etc. In fact these resources may likely be better suited to planning for writing, or using a common algorithm.

But what about:

  • How do I plan for Spring Security Authorization?
  • How do I get data from an iPhone to an Apple Watch that works when Watch is out of range?
  • How do I plumb a react.js page that is really correct for internationalized code that works for right to left AND left to right languages?
The list obviously goes on and on. These platform or framework specific algorithms and patterns are just as important as any low level tree walk design. In fact given their proliferation in so many environments, this is likely where people spend most of their time 'coding'!

So, how do we go from Pseudo code (perhaps 2 years and 3 versions old) that shows up on a search result, to a best practices for new or upgrading projects? How do we know, when using a swiss army knife style framework, that the pattern we picked is best for our project? How do we discover what we don't know we don't know? And how do we find this information quickly, without all the cruft, with just enough of the philosophy so we know we're heading in the right direction?