Friday, March 11, 2011

The i Programming Language - Part 1 - The Concept

Here is my idea for a new programming language. The language is called "i" for Internet, or interactive. The main difference between i  (or IPL) and other languages of today is the dynamic, or even unpredictable nature of i programs. This is achieved by using two key features:

A program written in i, every time it runs, uses:
  1. Different data. Input data is provided by Internet APIs like google search, flickr, youtube, amazon. For example when the program needs a picture of a a car, it grabs it from one of the free repositories on the Internet. Possibly, it grabs a different picture every time it runs. When a program needs encyclopedic information, it gets an article from wikipedia. When it needs a definition of a word: it uses a free dictionary or google's "define: this", when it needs a word translated, it uses and so on. It can use paid services too. It all depends on what libraries are available. And here we come to point 2.
  2. Different algorithms. Algorithms can be provided by libraries or functions found on the Internet. The i runtime engine, if it cannot find a requested library or function locally, starts searching around, maybe looking in a few hinted or well known places, or maybe all over the Internet, again using google search.
It is possible to write functions, or libraries that can be executed by any i program that finds them at runtime. Like the Internet is more than just a collection of web sites, an i program is more than just a collection of functions.

To make the language universal, and quick to accept, it compiles to JavaScript bytecode or is read and executed by an interpreter written in JavaScript. The i program, and the i libraries can be hosted inside regular html web pages. That's how they can be discovered quickly. A regular web search finds them.

The execution flow looks like this:
  1. A user requests a web page from a web server. The web page contains an i program in a native format plus an i interpreter written in JavaScript. Or it contains an i program already converted to JavaScript.
  2. The program starts running on page load event or when the user clicks a button or some other way. The program gets data, finds and calls other i programs using AJAX calls to i runtime engine hosted on a web server within the same domain, which in turn calls various Internet APIs. Note: the primary runtime environment is the browser, but the runtime on the server is needed to get past same origin policy, to make the i interpreter smaller and simpler, and to provide standard i libraries. The program is effectively running inside the user's browser downloading data and pieces of i code as it goes. It can also run code written in any language, executed on web servers, exposed using REST. Details to be defined.
  3. An i program can run forever, and can run simultaneously on an unlimited number of computers by spawning itself from the browser to servers that accept i code for execution.

Wednesday, March 9, 2011

My ruby zoo

Ruby is fun. A lot of fun. It makes programmers smile.  It makes them try crazy things... and those crazy things work.

Thank you Yukihiro Matsumoto!

Here is a little game I wrote with my kids one Saturday afternoon maybe a year ago.
There is an animal.rb and a zoo.rb and there is myzoo.rb which runs all that. I ran it using IronRuby.

class Animal
  # create accessor methods for reading these properties 
  attr_reader :attractiveness, :upkeep, :name, :age, :dies_at, :cost_to_buy, :current_value, :dead
  MAX_UPKEEP = 100

  ADVERBS = ["Small", "Big", "Smelly", "Cutest", "Sweetest", "Greenish", "Killer", "Harmless", "Angry"]
  NOUNS = ["Croc", "Elephant", "Hippo", "Ant", "Bear", "Mollusk", "Octopus", "Snake", "Snail"]

  def initialize(name)
    @attractiveness = rand(MAX_ATTRACTIVENESS)
    @upkeep = rand(MAX_UPKEEP)
    @name = name
    @age = rand(MAX_AGE_WHEN_BUYING)
    @dies_at = @age + rand(MAX_YEARS_TO_LIVE_AFTER_BUYING)
    @cost_to_buy = rand(MAX_COST_TO_BUY)
    @dead = false

  def Animal.get
    name = ADVERBS[rand(ADVERBS.length)] + " " + NOUNS[rand(NOUNS.length)]  

  def make_older
    return if @dead
    if age == @dies_at
       @dead = true
       puts @name + " died of old age."
       @age += 1
       @attractiveness -= 1

  def show
    puts "Name: #{@name}"
    puts "Attractiveness: #{@attractiveness.to_s} max: #{MAX_ATTRACTIVENESS.to_s}"
    puts "Cost to buy: $#{@cost_to_buy.to_s} max: #{MAX_COST_TO_BUY.to_s}"
    puts "Upkeep per year: $#{@upkeep.to_s} max: #{MAX_UPKEEP.to_s}"
    puts "Age: #{@age.to_s} year(s). max: #{MAX_AGE_WHEN_BUYING.to_s}" 
    puts "Dies at: #{@dies_at.to_s} year(s). max: #{(MAX_AGE_WHEN_BUYING + MAX_YEARS_TO_LIVE_AFTER_BUYING).to_s}" 
end # class Animal

class Zoo
  # ticket price can be set directly
  attr_accessor :ticket_price 
  # other properties are set internally 
  attr_reader :overhead_cost, :seed_money, :animals, :upkeep, :year, :animals_bought, :guests, :revenue, :cash

  def initialize()
    @animals =
    @upkeep = 0
    @overhead_cost = 100
    @ticket_price = 10
    @guests = 0
    @revenue = 0
    @seed_money = 500
    @cash = @seed_money
    @year = 0

  def show
    puts "Animals: " + @animals.length.to_s
    puts "Upkeep last year: $" + @upkeep.to_s
    puts "Overhead cost: $" + @overhead_cost.to_s
    puts "Ticket price: $" + @ticket_price.to_s
    puts "Revenue last year: $" + @revenue.to_s
    puts "Guests last year: " + @guests.to_s
    puts "Cash: $" + @cash.to_s
    puts "Year: " + @year.to_s

  # This defines how we buy animals:
  def buy_animal(animal)
      @cash = @cash - animal.cost_to_buy
      puts "You now have: $" + @cash.to_s
      @animals.push animal

  def next_year
    @upkeep = 0
    @animals.each do |animal|

    @animals.delete_if do |animal| 

    @animals.each do |animal|
         @upkeep += animal.upkeep

    @guests = 0
    @animals.each do |animal|
        @guests += animal.attractiveness
    @guests = (@guests/Math.sqrt(@ticket_price)).to_i
    @revenue =  @guests * @ticket_price
    @cash += @revenue - @overhead_cost - @upkeep
    @year += 1

end #class Zoo

require "zoo.rb"
require "animal.rb"

SCORES_FILE = "scores.txt"

def show_hall_of_fame, CREATE_OR_APPEND_MODE) {}
  scores = IO.readlines(SCORES_FILE) 

  puts "Hall of fame: "
  puts " waiting for your name" if scores.length == 0
  puts scores if scores.length > 0

def update_hall_of_fame (cash, player), CREATE_OR_APPEND_MODE) {}
  scores = IO.readlines(SCORES_FILE) 
  scores[scores.length] = format("%10.10s %s", cash.to_s, player) 
  scores.sort!.reverse!, WRITE_MODE) {|f| f.write(scores) }

def show_menu
  puts "b = Buy Animals"
  puts "s = Sell Animals" 
  puts "p = Set Ticket Price" 
  puts "a = Show Animals" 
  puts "z = Show Zoo" 
  puts "n = Next Year" 
  puts "h = Hall of Fame" 
  puts "q = Quit"

puts "Welcome to MyZoo!"
puts "You manage it. Try to make as much money as you can in #{YEARS_TO_PLAY.to_s} years."

print "What's your name boss? "
player = gets

myzoo =

puts "You have in the bank: $" +

playing = true

while playing and myzoo.year <= YEARS_TO_PLAY do
  print "Enter command:"
  command = gets

  case command
    when "b\n"
      some_animal = Animal.get
      print "Do you want to buy this animal? (y/n) "
      answer = gets
      myzoo.buy_animal(some_animal) if answer == "y\n"
    when "s\n" 
      if myzoo.animals.length > 0
         puts "Your salesperson has been eaten by #{myzoo.animals[0].name}." 
         puts "There is no fauna in your zoo."

    when "p\n" 
      print "New ticket price: "
      answer = gets
      if answer.to_i > 0
         myzoo.ticket_price = answer.to_i  
         puts "Sorry, no free tickets this year." 

    when "a\n" 
        if myzoo.animals.length > 0 
           puts "Your animals: " 
           myzoo.animals.each do |animal|
           puts "Did you buy any? Are they still alive?"

    when "z\n"    

    when "n\n"

    when "h\n"

    when "q\n"
      print "Abandoning your enterprise? (y/n)"
      answer = gets
      if answer == "y\n" then 
         puts "Good-bye!"
         playing = false

update_hall_of_fame(, player) if > 0

Tuesday, March 8, 2011

"Marek Edelman. Życie. Po prostu." by Witold Bereś and Krzysztof Burnetko.

I have read this 500 page book in Polish. The English title is "Marek Edelman: Simply A Life". A 30 minute DVD is included with the book. It shows Edelman being interviewed by the authors for the book.

This book is for you if you are looking for a first hand account of what the relations between different groups of Jews and Poles were in pre-war Poland, during the war, and after.

This book tells the story of the first Warsaw uprising - the Ghetto uprising - as it was: without pathos. It is a shocking story, but told without big words or hatred.

This book also tells a more general story. This book is for you if you are looking for inspiration how to live your life. What is important.

A few quotes by Marek Edelman:
"In life, those who let others live, are right."
"In principle, life is most important. And if you live, then the most important thing is freedom. And then you give life for freedom. And then you don't know what is most important."
"I am a Polish Jew, but Ala [wife] and all Jews think that I am a disgusting polonophile, and that I have a character of a Pole. But I think that patriotism is disgusting. I would never say about myself that I am a patriot - I am a patriot of the idea of freedom everywhere."
And finally:
"In life, I like caviar and beautiful girls."

The Associate by John Grisham

Read by: Erik Singer

Another story from the world of lawyers. We meet Kyle McAvoy when he is a senior at Yale law school. He is about to graduate and start a career in public law, but someone sinister has other plans for him. What will Kyle do with his life? Will he follow his ideals or will he give in to the dark side?

Monday, March 7, 2011

Language Implementation Patterns by Terrence Parr

Rating: Lot's of information, but poorly presented.

Basic Patterns:
  • Mapping Grammars to Recursive-Descent Recognizers: convert formal language specification (grammar) into a parser.
  • LL(1) Recursive-Descent Lexer: break up character streams into tokens.
  • LL(1) Recursive-Descent Parser: make a parsing decision (choose parsing method) for the current (1) input symbol.
  • LL(k) Recursive-Descent Parser: make a parsing decision (choose parsing method) for up to k next input symbols.
  • "A language is just a set of valid sentences."
  • "To parse, then, is to conjure up a two-dimensional parse tree from a flat token sequence."

This book could have been much better. It suffers from the following problems:
  •  Code examples:
    • Incompleteness - critical functions are missing initially: code which uses match() starts on page 41, but match() implementation is shown on page 55 for the first time.
    • Names of variables and functions are cryptic/not clear and do not follow one convention: 
      • variable names: T, p, c, x, k, i, r, Integer memoI, int memo, FOLLOW_INT_in_point37, _save,
      • function names: LT(), LA(), isSpeculating(), alreadyParsedRule(), _list(), speculate_stat_alt1().
  • Critical terms are used without introduction.
  • Definitions seem chaotic/incomplete.
  • Concepts are introduced in chaotic order.
  • Some concepts seem to change meaning: current token becomes a lookahead token.
  • There is a lot of alternative terminology that is used without introducing it properly: here are my notes on  "lexer":  Lexer: a type of recognizer; aka scanner, aka lexical analyzer, aka tokenizer: reads a stream of characters and yields a stream of tokens aka input symbols, aka vocabulary symbols.

Software Creativity by Robert Glass

Rating: A critical look at formal methods as a solution to all.

By page 19 (and 13 pages of forewords) we learned that there are two opposite views of how software should be developed: disciplined and flexible, and that the author will in the end show us that the middle way is the best.

Author's theory about software practice includes these issues:
  • Discipline vs. flexibility
  • Formal methods vs. heuristics
  • Optimizing vs. satisficing (sic!)
  • Quantitative vs. qualitative
  • Process vs. product
  • Intellectual vs. clerical tasks

On page 268 there is a good list of what academic research should be focusing on, two of which seem especially worthy:
  • issues contrary to commercial interests,
  • unsolved problems.

I think that definition of standards with sample implementations might fall into the "contrary to commercial interests" category. This might prevent the "design by committee" problems that we see in CORBA and IATA CUSS standards.

Chapter 9 contains an interesting discussion of "fun" in software development. The author references a paper by Bruce Blum, who lists the fun/tedium ratio for different phases of SDLC:
  • "selling the concept" phase - pure problem solving/analysis phase: 100% fun - 0% tedium
  • writing down requirements: 50-50
  • top-level design: 40-60
  • detailed design: 33-67
  • programming: 75-25
  • testing: 33-67
  • maintenance: 0-100

Chapter 9.3 mentions another interesting idea for creating projects with higher ratio of fun - the "incremental consensus" technique by Jerry Weinberg: begin with 2 people who want to work in a mutually pleasing manner and succeed on a project, then grow the team in increments of 1 and only when the candidate gets everyone's acceptance.

Chapter 13 lists ideas on how organizations can become more creative:
  • support open sharing of information
  • support risk-taking behaviors
  • create group diversity
  • create highly participative culture
  • create "slack resources"

Chapter 14 lists traits of creative people.

Chapter 15 shows that computer tools can decrease creativity in problem solving.

Chapter 16 explains creativity paradoxes:
  • The more you know about the problem domain, the less creative your solutions are.
  • To come up with creative solutions, you must know how others solved it.

Chapter 17 shows that software life cycle is just an implementation of a universal problem solving algorithm:
  • Identify a problem.
  • Define the requirements of the problem.
  • Design a solution to the problem.
  • Implement the design.
  • Test the implementation.
  • Use the implemented product.

What I am missing in this book is the word "pragmatic". It is a simple, elegant, and "to the point" summary of the approach that Robert L. Glass postulates to use for software development.

Rapid Development by Steve McConnell

Rating: Instruction manual for software projects.

Chapter 7 - Lifecycle Planning - has a surprise for those who think that "Agile" and "SCRUM" are new revolutionary concepts. This book was written in 1996 and the Evolutionary Prototyping, Staged Delivery, Design-to-Schedule, and Evolutionary Delivery processes described there look eerily familiar to us.

There is a very interesting table on page 156: Lifecycle Model Strengths and Weaknesses. The Spiral model is a clear winner.

Chapter 9 - Scheduling - explains what the estimated completion date really is. "Developers typically estimate 20 to 30 percent lower than their actual effort. Merely using their normal estimates puts the chance of completing on time below 50%".

Chapter 11 - Motivation - has interesting insights about developers and managers. For example: "Compared to the general population, developers are much more motivated by possibility of growth, personal life, opportunity for technical supervision, and interpersonal relations with their peers. Developers are much less motivated by status, interpersonal relationships with subordinates, responsibility, and recognition."

Percentage of computer professionals who have a preference for:

  • introverted (I) over extroverted (E): 58%... I = interested in ideas rather than people and things,
  • thinking (T) over feeling (F): 80%... T = logical, objective decisions,
  • judging (J) over perceiving (P): 66%... J = live in a planned, orderly way.

Chapter 43 - Voluntary Overtime - shows in a Machiavellian way how to trick developers into producing more without compensation. It's tricky, but it can be done. Other ways DO NOT work. Involuntary or excessive overtime decreases overall productivity. "Trying to motivate developers can be like trying to push on a rope - you'd be better off pulling on the other end."

Key Lessons:

  • Software development can be optimized for schedule, quality, performance, maintainability, usability, cost. Pick one or make trade-offs.
  • To get software on time you must:
    • not make classic mistakes,
    • follow software development fundamentals,
    • manage risk,
    • use schedule-oriented practices.

Rapid Development complements Code Complete. It gives team leads and managers knowledge with which they can deliver software projects on time.

Applying UML & Patterns 3rd Edition by Craig Larman

Rating: Too many words. Too little essence. Messy. Academic.

This 700 page book could be easily re-edited to fit 400 pages or less. There are very few original ideas here. There is a lot of repetition, obvious statements, outside of topic statements, defensive statements, and meta-content. There was one bit of wee humor in the first 240 pages, but I did not write it down immediately, and now I cannot find it. :-(

This book looks like an attempt at jumping on the agile development bandwagon, by someone who preached for ages a complex, UML and roles driven, approach to software development, and now is very apologetic about it.

Chapter 22 tells us that UML is used as a sketch, as a blueprint, and very rarely as a programming language.
Chapter 22 contains also this breaking piece of news: '''developers consistently report that UML tools seem to "get in the way" more than help''' - page 396.

The CUPPS standard defines "log in" and "log on" as 2 different operations. In the same fashion this book on page 594 defines "fault", "error", and "failure" as 3 different terms. Which normal person is going to remember what is what?

Conceptual Blockbusting: A Guide to Better Ideas by James Adams

Rating: Boring, except for one or two puzzles.

This book shows you how to be more creative by discovering where your blocks are and how to break them. Your thinking process may be constrained by blocks originating in: perception, emotion, culture, environment, intellect, expressiveness.


  • using alternate (to verbal) thinking languages: mathematical, sensory (visual, etc.).
  • questioning attitude
  • finding the core problem
  • making lists
  • combining alternate attributes
  • trying manipulative verbs
  • getting input from other people, especially coming from other disciplines, cultures, environments

Method of loci (locations in Latin): associate physical locations with items that you want to remember. Take a walk in your head to recall the items.

Programming Pearls 2nd Edition by Jon Bentley

Rating: Devilishly difficult sometimes, but valuable. I will read it again one day.

  • Principles from Column 1: 
    • ''The Right Problem''', 
    • The Bitmap Data Structure, 
    • Multiple-Pass Algorithms, 
    • A Time-Space Tradeoff and One That Isn't, 
    • A Simple Design, 
    • Stages of Program Design.
  • "don't write a big program when a small one will do" - page  29
  • "the more general program may be easier to solve"
  • "back of the envelope" calculations - page 67
  • Rule of 72
  • Little's Law: "The average number of things in the system is the product of the average rate at which things leave the system and the average time each one spends in the system." - page 73
  • save state to avoid re-computation - page 84
  • pre-process information into data structures, divide and conquer, scanning, cumulative
  • Good programmers keep efficiency in context: it is just one of many problems in software, but it is sometimes very important. - p.87

  • If we assume that we have a "reverse" function, why not assume that we have a rotate function, and be done with it? - Column 2
  • Variables in examples have almost always 1 letter names: m, n, i, x, l, t.

Bottom Line:

What makes this book difficult to read is the mathematical approach.

The problems are not common - almost nobody is writing their own search algorithms, or random number generators nowadays - but they provide insight into how things work. For example why it is a good idea to tell the hash class at initialization the approximate number of elements.

This book is a hard one. I feel like I need to read it again, do some exercises, and feed the Mnemosyne.

Code Complete 2 by Steve McConnell

Rating: The Bible of Programming. Every developer can learn a few things from it
and have an occasional laugh.

  • heuristics vs algorithms
  • metaphors for making software: 
    • penmanship: writing code, 
    • farming: growing a system, 
    • oyster farming: system accretion, 
    • construction: building software.
  • good practices differ for different kinds of software projects: business systems, mission-critical systems, embedded life-critical systems - page 31
  • typical architectural components: program organization, major classes, data design, business rules, user interface design, resource management, security, performance, scalability, interoperability, internationalization/localization, input/output, error processing, fault tolerance, architectural feasibility, over-engineering, buy vs. build decisions, reuse decisions, change strategy, general architecture quality.
  • technology wave - page 66
  • programming into a language (good) vs programming in a language (bad) - page 68
  • a "wicked" problem - one that can be clearly defined only by attempting to solve at least part of it - page 74
  • accidental and essential difficulties - page 77
  • desirable characteristics of a design: 
    • minimal complexity, 
    • ease of maintenance, 
    • loose coupling, 
    • extensibility, 
    • re-usability, 
    • high fan-in: having a high number of classes that use a given class, 
    • low-to-medium fan-out: having a given class use a low-to-medium number of other classes  (high cohesion), 
    • portability, 
    • leanness: designing the system so that it has no extra parts, 
    • stratification - design the system so you view it at one level without dipping into other levels,
    • standard techniques - page 81
  • design building blocks: 
    • major heuristics: find real-world objects, form consistent abstractions, encapsulate implementation details, inherit - when it simplifies the design, hide secrets, identify areas likely to change, keep coupling loose, look for common design patterns
    • minor heuristics: aim for strong cohesion, build hierarchies, formalize class contracts, assign responsibilities, design for test, avoid failure, choose binding time consciously, make central points of control, consider using brute force, draw a diagram, keep your design modular
  • design practices: iterate, divide and conquer, top-down and bottom-up approaches, experimental prototyping, collaborative design
  • Abstract Data Type (ADT) - page 126
  • semantic encapsulation - page 141
  • Liskov Substitution Principle (LSP) - you shouldn't inherit from a base class unless the derived class truly "is a" more specific version of the base class - page 144
  • "mixins" - classes, usually abstract, meant to be inherited from in multiple inheritance - page 149
  • shallow copies (reference objects) vs deep copies (value objects) - page 152
  • "gold-plating" - creation of functionality that isn't required and that unnecessarily adds complexity - page 154
  • "god class" - a class not to create - page 155
  • types of acceptable cohesion in a routine - page 168:
    • functional - performs one and only one operation - the ideal,
    • sequential - contains operations on shared data that must be performed in a specific order,
    • communicational - operations share data, but are otherwise unrelated,
    • temporal  - contains operations that are done at the same time.
  • types of unacceptable cohesion in a routine - page 170:
    • procedural - operations performed in order matching UI,
    • logical - performs one of contained operations based on an input flag,
    • coincidental - no relationship between operations.
  • defensive programming
  • assertions - "Error handling typically checks for bad input data; assertions check for bugs in the code." - page 191, but "For highly robust code, assert and then handle the error anyway" - page 193
  • preconditions
  • postconditions
  • robustness vs. correctness - page 197
  • barricade - page 203
  • debugging aids - page 205
  • PPP - pseudocode programming process - page 215
  • Principle of Proximity - keep related actions together - page 242
  • window of vulnerability, variable span - average number of statements between variable references, variable live time - max number of statements between references - page 245
  • hybrid coupling - two variables in one - page 256
  • the telephone test - "[...] if you can't read your code to someone over the phone, rename your variables to be more distinctive [...]" - page 283
  • write-time convenience vs. read-time convenience - page 285
  • dog-tag - a field added for error checking - page 326
  • tramp data - data passed to a routine only to be passed to another routine - page 338
  • guard clause - code that exits a routine early if it is not ok to proceed, to avoid deep nesting - page 392
  • safety counter - a counter variable that prevents infinite loops - page 396 and earlier
  • cyclic recursion - A calls B, B calls C, C calls A - page 396
  • table-driven approach - lookup information in a table rather than using logical statements - page 411
  • indexed access tables - page 425
  • stair-step access tables - page 426
  • DeMorgan's Theorems - use to simplify boolean tests - page 436
  • structured programming - you can build any program out of a combination of sequences, selections, and iterations - page 454
  • McCabe's cyclomatic complexity metric - the sum of decision points in a routine - 10+ is possibly too complex - page 458
  • quality gates - page 467
  • collaborative construction - page 480
  • formal inspections - page 485
  • walk-through, code reading, dog-and-pony show - page 492
  • black-box/white-box testing - page 500
  • structured basis testing - page 507
  • data flow testing - page 509
  • equivalence partitioning, error guessing, boundary analysis, compound boundaries, classes of bad/good data- from page 512
  • system perturbers - page 527
  • confessional debugging - page 547
  • brute-force debugging - page 548
  • voodoo programming - page 553
  • psychological distance - page 556
  • code-tuning: loops: unswitching, jamming, unrolling, sentinel values - page 616
  • strength reduction - page 630
  • phased vs incremental integration - page 691
  • top-down vs bottom up integration - page 694
  • integration types: sandwich, risk-oriented, feature-oriented, T-shaped - page 698
  • Fundamental Theorem of Formatting - page 732

Bottom line:

  • "Specifying requirements adequately is a key to project success [...]" page 39
  • "Once you understand that all technical goals in software are secondary to managing complexity, many design considerations become straightforward." - page 79
  • "Design is heuristic. Dogmatic adherence to any single methodology hurts creativity and hurts your programs." - page 123
  • "If a routine has bad cohesion, it's better to put effort into a rewrite to have better cohesion than investing in a pinpoint diagnosis of the problem." - page 169
  • "The name of a routine is an indication of its quality." - page 186
  • Define quality goals - page 469
  • "[...] effective software-quality program must include a combination of techniques [...]" - page 473
  • "[...] inspections quickly brought all the developers up to the level of the best developers [...]" - page 482
  • "The first priority of visual layout is to illuminate the logical organization of the code." - page 775.
  • "Holy Grail of legibility: self-documenting code. [...] In well-written code, comments are the icing on the readability cake." - page 779
  • Good comments: "[...] information that can't be expressed in code, intent comments, and summary comments." - page 788
  • "If you're figuring out code instead of reading it, it's too complicated. If it's hard, it's wrong. Make it simpler." - page 849
  • "A blanket attempt to avoid mistakes is the biggest mistake of all." - page 852

:-) Funny bits:

  • "In programming, if your requirements are contaminated, they contaminate the architecture, and the architecture in turn contaminates construction. This leads to '''grumpy, malnourished programmers''' and radioactive, polluted software that's riddled with defects."
  • "It's as if you were a contractor called to work on a house. Your customer says, "What will it cost to do the work?" You reasonably ask, "What do you want me to do?" Your customer says, "I can't tell you, but how much will it cost?" You '''reasonably''' thank the customer for wasting your time and go home."
  • Comparing productivity of higher and lower level languages: "You save time when you don't need to have '''an awards ceremony''' every time a C statement does what it's supposed to." - page 62
  • "You'd probably want to '''tar and feather''' a teacher who gave you a programming assignment, then changed the assignment as soon as you finished the design, and then changed it again just a s you were to turn in the completed program. But the very process in an everyday reality in professional programming." - page 75
  • "[...] the road to programming hell is paved with global variables [...]" - page 95
  • "A vague, wishy-washy [routine] name is like a politician on the campaign trail. It sounds as if it's saying something, but when you take a hard look, you can't figure out what it means." - page 222
  • "[About memory initialization] Alternatively, Brian Kernighan and Rob Pike suggest using the constant 0xDEADBEEF as a memory filler that's easy to recognize in a debugger [...]" - page 244
  • "You can't give a variable a name the way you give a dog a name - because it's cute or it has a good sound." - page 259
  • The optimum length for a name seems to be somewhere between the lengths of x and maximumNumberOfPointsInModernOlympics." - page 262
  • "It's OK to figure out murder mysteries, but you shouldn't need to figure out code." - page 267
  • "FALSE [...] would be a bad abbreviation for 'Fig and Almond Season'" - page 285
  • "By the time structured programming came and went, the term 'structured' had been applied to every software-development activity, including structured analysis, structured design, and '''structured goofing off'''." - page 454
  • "[...] compilers are dissembling little rascals, [...]" - page 549
  • "Some compilers get so excited after detecting the first error that they become giddy and overconfident; they prattle on with dozens of error messages that don't mean anything." - page 550
  • "Code as if whoever maintains your program is a violent psychopath who knows where you live." - page 777

Interesting observations:

  •  7 +/-2 is a number of discrete items a person can remember while performing other tasks. If a class contains more than about seven data members, consider splitting it into smaller classes. - page 143
  •  "A good way to think of assertions is as executable documentation [...]" - page 191
  •  "[...] code reviews were several times as cost-effective as testing [...]" - page 473


  • The Java Singleton example on page 151 is not correct, because it does not close the class for inheritance
  • The "Avoid classes named after verbs" recommendation on page 155 does not mention the Strategy pattern, where naming your behavior classes after verbs may be desired
  • The Visual Basic example of a centralized exception reporter on page 202 does not follow the rules of defensive programming (no parameter validation) and the law of Demeter ("thisException.TargetSite.Name"). ReportException() may itself throw an exception in some cases.
  • Some abbreviation guidelines on page 282, like "Remove all nonleading vowels", "Keep the most noticable sound in each syllable" make the code difficult to read for non-native English speakers.
  • The concept of coding into a language may be misused to make a C# program look and act like a COBOL program.
  • The author mentions C++, and Java often, but skips C# which has the same features - page 439
  • Writing numeric expressions in number-line order makes them difficult to read: you have to start in the middle of the line and read to the left and right at the same time. It looks good when you draw it, but it is awkward to read - page 440

Sunday, March 6, 2011

UML Distilled by Martin Fowler et all

Rating: Concise. Worth returning to.

Finally, there is a book about UML written by a practitioner for practitioners. It even has code samples that make sense. Nice.

The only complaint I have at the moment is the amount of forewords and prefaces: 10 pages for a book that has 159 pages of content.

All right, so what did I get out of this book?

  1. Use '''UML as sketch''' to help communicate design ideas.
  2. Everything in UML is optional, so when reading a diagram do no make assumptions based on something not being present.
  3. It is ok to use non-standard notations, if they are better known, or simpler - be pragmatic - the goal is for your audience to understand your design.
  4. There are also useful, non-UML diagrams, like the screen flow diagram, and the decision table.
  5. It is very difficult to get UML right before coding, therefore using UML as blueprint in forward engineering may not be efficient.

This book should be read twice and should be kept around for reference.

Scrum and XP from the Trenches by Henrik Kniberg

Rating: Very interesting.

I've read this one initially at the end of 2006. Lots of interesting,
real-life observations.

Scrum Concepts:

  • velocity (aka actual velocity) - the sum of all initial estimates of story points, for stories completed in one sprint,
  • estimated velocity -  the sum of all initial estimates of story points, for all stories planned for one sprint,
  • external vs internal quality (visible to the user or not)
  • yesterday's weather - look back several sprints and average out the estimates
  • taskboard - index cards for stories, and post-it notes for tasks on a wall, grouped into: not checked out (stories and tasks), checked out (tasks), done (stories and tasks), unplanned items, next (stories), aka: sprint goal, burndown chart
  • seat the team together for audibility, visibility, isolation:  
    • audibility - any team member should be able to talk to any other team member without shouting or leaving his/her desk
    • visibility - any team member should be able to see any other team member and the taskboard without leaving his/her desk
    • isolation - the team does not disturb anyone else, and nobody disturbs the team
  • "knowledge bridge" person - a person attending all retrospectives
  • insert a lab day between sprints - page 74
  • acceptance thresholds - for release planning and fixed price contracts
  • all-hands pulse meeting - weekly, 15 minutes, the teams share information about what they are doing
  • the firefighting team - a temporary team that protects scrum teams from interruptions by fixing bugs, or finishing old business

Code Branching Tips:
 * trunk should always build
 * tag each release
 * when in doubt, do not branch
 * synchronize often

XP Concepts:
 * pair programming
 * test-driven development
 * incremental design
 * continuous integration
 * collective code ownership
 * informative workspace
 * coding standard
 * sustainable pace / energized work

Interesting observations:

  • for keeping product backlog, the product owners preferred shared Excel file to a bug tracking system, because the Excel file required fewer clicks
  • internal quality should not be negotiable
  • 3 week sprints worked best
  • a meaningful sprint goal is important to keep the team focused
  • sprint backlog is initially defined as a list of stories from product backlog, not tasks; later in chapter 6, the associated tasks are shown on the taskboard
  • product backlog has the following pieces of information: ID, name, importance, initial estimate, how to demo, and notes - all are printed on cards for the planning meeting
  • tasks estimated in story points (ideal days), down to 0.5
  • demo of a technical story does not have to be a demo on a computer, it can be a piece of paper showing test results - page 66
  • code review is an OK alternative to pair programming
  • most teams do not include acceptance testing in the sprint, because it cannot be time-boxed

"TDD is hard, but trying to do TDD on a code base that wasn't built using TDD from start... that's really hard! [...] Lesson learned: If you are stuck with having to do manual regression testing, and want to automate this away, don't (unless it is really easy). Instead, build stuff that makes manual regression testing easier. Then consider automating the actual testing."

Tools/frameworks mentioned in context of TDD:
jUnit, httpUnit, TestNG, Selenium, HSQLDB, Cobertura, Spring

Agile Project Management with Scrum by Ken Schwaber

Rating: Intended for Scrum masters.

Quick comments:
A bit academic. Dedicated to Scrum masters, not developers. For Scrum essentials go to Appendix A: Rules.

:-) Funny bits:

"It is possible to have simple software requirements. A single customer who is the only person who will use the system can spend enough time with the developer that the two can agree exactly what to build. Assuming that this customer '''dies immediately [...]'''"

"You notice that the commissioner gets increasingly agitated during your presentation, tapping his feet, '''spitting at the floor''', and uttering muffled expletives. He appears to be very unhappy." - page 78.

empirical process control (visibility, inspection, adaptation) vs defined process control, stakeholders, complexity assessment graph, scrum skeleton, product backlog (sprint stories [0.5-n days]), Scrum
roles (product owner, the team, Scrum master), sprint, planning meeting, sprint backlog (sprint tasks [4-16 hours]), daily Scrum, sprint review meeting, sprint retrospective meeting, burn-down chart, adjustment (complexity) factor, the art of the possible, self-organizing team, time-boxing, incremental delivery, sashimi,
sprint goal, changes report, product backlog burndown report, suboptimal measurement, scaled project, daily scrum of scrums, staging.

Bottom line for us, the developers:
Scrum is about letting the team estimate the work (stories) initially, divide them into tasks, assign within the team, estimate work left to do every day, and present results every 30 calendar days (sprint). Scrum is about product owners defining, prioritizing, and providing feedback on the work. Scrum allows product owners to see in great detail how the work is progressing daily, and change course if necessary.


"The process of developing functionality includes: analysis, design, coding, testing and documentation."

"During this training, I emphasized that '''Scrum Masters have no authority over the development teams'''; they are present only to ensure that the Scrum process is adhered to and that the teams' needs are met." - page 103.

Interesting observations/Criticism:
  • testers are not part of the team at MegaBank, QA starts at the end of every sprint - page 72, however, in other cases, they are part of the team
  • there is a special, 2 week, release sprint at MegaEnergy - page 91
  • the definitions and index do not include velocity which is an important scrum concept