C. Keith Ray

C. Keith Ray writes about and develops software in multiple platforms and languages, including iOS® and Macintosh®.
Keith's Résumé (pdf)

Wednesday, June 12, 2019

Advice to a young programmer

Someone on Quora asked:

"I make so many mistakes while coding. All code reviews get lot of review comments and sometimes it’s create regression on the system too. Am I not good for developer role?"
My answer:

Sometimes review comments are more about the commenter than the code or you: they're telling you how THEY would write the code rather than evaluating the code on its own merits.

On the other hand, causing regressions is not at all desireable. Why didn't the reviewers catch the source of the regression? Did you have tests you should have run before checking in the code? What could you have done to find the side-effects of your changes?

Keep a journal: what did the code look like before the review and after changes required or requested by the reviewers. Do you understand why the "after" code is better? Are there things you didn't know that you needed to do?

Also journal your bugs and bug-fixes. When you make a fix, did you look for other places in the codebase with the same or similar problems? Can you fix that code too?

You can learn most rapidly if you pair-program. (Google it. There's a book on that subject.) Can you pair-program bug-fixes or new code with a partner? As a junior programmer, you should "drive" while the experienced programmer "navigates". 

Or try Mob Programming: the whole team can learn and code at the same time. You can also pair program with testers (to replicate and fix a bug) and/or analysts/designers (implementing new features), though they will have less to teach you about coding.

Software development is exacting. One semi-colon in the wrong place can create a  bug that may not show its effects for years. That bug could be harmless or it could cost multiple companies millions of dollars. In this paragraph, I used "its", which is the possessive version of "it". Many people, whether native English speakers or not, would have incorrectly used "it's", which is the contraction of "it is". You have to have the same level of knowledge for your programming languages and development tools as I have for English.  (Also, it's a rule that whenever someone writes about correct English grammar or spelling, they will make a mistake or two.)

Beware of cutting and pasting code from Stack Overflow: a lot of it is wrong or out of date. You need to understand why the code offered in SO is right or wrong for your situation.

If being extremely detail-oriented and knowledgeable about your code is too hard for you, then programming may not be your best career choice. I don't want to say that programming has to take over your life, but mastering it will take commitment and time. 

Comedian Bob Newhart joked that as an accountant, he was happy getting the books almost right. He said his bosses didn't find that funny. So he quit accounting and became a famous stand-up comic/actor.


Wednesday, June 5, 2019

Writing Exercise - Action genre

This is a writing exercise. It is fiction. It is not meant to be scientifically accurate. I'm pretty sure I've got several details wrong.

Tah’dt and Zhei’Sun were tracking an immature mammoth through the brush when the wind shifted, bringing the acrid scent of a saber-toothed tiger to their attention. It was very likely the female tiger known to the tribe as Less Lee, hunting the same mammoth. Less Lee had killed Zhei’Sun’s mate, B’Uff Eee, when she was hunting small game earlier that summer — it wasn’t afraid of The People. If they got in the way of Less Lee hunting the mammoth, she would be happy to kill them and the mammoth, feeding her mate, sisters, and adolescent cubs for days.

Tah’dt peered around him. Broken branches and underbrush led deeper into the forest on his right. The mammoth was foraging for young shoots, making a lot of noise in the process, but there were few fresh shoots this late in the summer. Tah’dt and Zhei’Sun had stayed on higher ground, off the mammoth’s trail. There! A glimpse of tiger stripes in the underbrush confirmed the tiger’s presence. It was on the other side of the trail, and closer to it. It was a mature saber-tooth, nearly as tall walking on all fours as B’Uff Eee’s mother was standing erect, who had been tall for a woman. It probably weighed as much as four well-fed men. Its claws would be as large as Tah’dt’s hands, and its incisors as large as Zhei’Sun’s head. Zhei’Sun had a big head.

In previous times, when The People were well-fed, they would have abandoned the hunt. Better to let the tiger have the young mammoth than to lose seasoned hunters. Coming home empty-handed from a hunt was bad for a hunter’s reputation, but in times of plenty, it would merely be a source of jokes. This summer had been much hotter than normal. The river was down to a trickle and and their food plant had died. Prey animals were hard to find. Coming home with nothing to eat would mean death for weaker members of the tribe. Tah’dt’s two-year-old girl-child was already just skin-and-bones. They could not give up this hunt.

Tah’dt pointed the tiger out to Zhei’Sun, and signed for him to wait for the tiger to advance out of sight. They might be able to kill the tiger while it was attacking the mammoth, hopefully after it had wounded it. Then there would be enough food for a while, and removing a predator from the area also meant more food for The People. They waited with stillness of experienced hunters, not even flicking flies away from their sweat-soaked hair. The mammoth herd, while out of sight, could be heard occasionally, as the males signaled their “all is safe” sound. Tah’dt devised a plan. He whispered it to Zhei’Sun. He nodded agreement and started quietly making his way back to the tribe’s shelter.

Clutching his spears, Tah’dt crept along the high path, keeping the young mammoth’s path in sight. The wind stayed favorable; it seemed likely that the tiger hadn’t sensed him, yet. Eventually he saw the mammoth. It was in a shady area where a creek used to run through the forest. It was tearing up the underbrush with its tusks, grabbing green plants with its trunk. Tah’dt looked for the tiger. It had to be near, but he didn’t see it. Would his tribe’s men get here in time?

A bird call came from where he had been. Tah’dt looked and saw Zhei’Sun signing that the men were in place. Tah’dt signed them to wait. Before he knew it, the saber-tooth tiger had leapt from concealment onto the mammoth. They began to struggle fiercely. Tah’dt signaled Zhei’Sun, and they all advanced with their short spears in one hand, their long spears in another, and their daggers hung in their belts. They surrounded the shady area and waited for an opening to attack the tiger and the mammoth.

The mammoth was old enough to match the tiger in weight, but it was inexperienced and fought poorly. Soon it was bleeding from several slashes. As it struggled for its life, Tah’dt and some others threw their short spears at the tiger. Their hits drew blood. The tiger hissed and rounded on them, but they kept out of its reach, brandishing their long spears. 

Zhei’Sun cried out when another saber-toothed tiger pounced on him from a tree! It was one of Less Lee’s sisters! It slashed his neck with its long teeth and he was dead. Tah’dt and the other men backed away but didn’t run away. If they kept close together they could maybe survive this.

The young mammoth whimpered as it continued to struggle against Less Lee on its back. The tiger was suffocating the mammoth because it wasn’t able to slice through the thick coat over the mammoth’s throat. It was still alive but it had no chance against two tigers.

Tah’dt handed his long spear to the man next to him, who was shocked he would disarm himself like that. He took a breath, and put both hands over his mouth. Tah’dt made the distress call that the young mammoth in front of his should have been making. He did it again and again while his tribesmen brandished their long spears.

They heard the rumble and saw the brush shaking as two adult mammoths burst onto the scene. They were a male and a female; they might even be the young one’s sire and dam. The tiger on Zhei’Sun fled immediately. Less Lee was encumbered long enough for the male to attack her, first with a tusk, then pulled off and thrown by a trunk. 

Tah’dt and his men threw their spears into Less Lee, mortally wounding it. The female adult mammoth slashed Less Lee with a tusk. The tiger coughed and died.

Tah’dt and his men pulled out their daggers. At his signal, they moved back into the underbrush until they were out of sight of the mammoths.

The female mammoth caressed the young one, but its wounds were too much; it would be dead soon.

When darkness descended, Tah’dt and his men came back, bearing torches. They prayed thanks for the gift of food, and began butchering the mammoth, the tiger, and their friend. The People would live for a while longer.


Wednesday, April 17, 2019

Second Program

The University of Texas in Arlington kept its computers in the basement. Since a computer in 1981 weighed as much as a Chevy Impala, only the basement floor was strong enough to hold it. The basement wasn't damp and dark, it was brightly lit with fluorescent lights, dry, and over-air-conditioned. I was in a room adjacent to the computer. Ordinary students were not allowed in same room as the computer. I adjusted my shirt; sweat had formed between the time I got out of my car and into the basement. Normal for a Texas summer.

I was a student in the "Summer Sciences Institute in Physics" for high school students. An accelerated course, heavy on math. It was tough but fun. We were over-achievers from several high schools. We had been given access to this computer to analyze data from an experiment. 

I sat in an uncomfortable chair, at a plastic, faux-wood-topped table and wrote FORTRAN code by hand on paper, in pencil, because I would have to correct errors as I wrote and analyzed the problem and the code. I had a physics book, a book on FORTRAN, and a hand-out to refer to. It wasn't hard, but it was tedious. A few lines of that code looked like something like this:

        DO 20 J = 1, N
        SUM = SUM + SQR(X(J))
    20  CONTINUE

Then, sitting in front a punch-card writer, I typed in that code. One line of code per punch-card. Eventually, I held a short stack of punch-cards in my hand. With my pencil, I drew a diagonal line on the card edges so that, if I dropped the cards, I could could fairly easily get them back in order.

It was time to run the program. Trying to act nonchalant, I silently handed the deck of cards to the bored college student who was system operator for that lab. He dropped them into a card-reader and punched a button. Whirr-hiss-thump: the cards I had spent a half-hour typing were read by the computer in a second. He handed back my cards.

Fifteen minutes later, a printer the size of a dishwasher clattered, loud, even though it had a transparent cover. My name, and the results of my program, appeared on form-feed paper two feet wide, pre-printed with thick, light green, bands of color. The system operator tore off the pages and left them for me on a table.

It worked! A sophisticated electronic device had followed my instructions. That was my first program. Now I wanted to do something for fun. I wanted the computer to print out something visually interesting. Back to the table. I decided to print a sine wave. This computer system had no graphics, so I would have to print characters to form a picture. I decided to print a sine wave.

I wrote the code, typed it onto punch cards. To save time, I re-used several cards from my first program. Again, whirr-hiss-thump

My mouth was dry. We weren't supposed to be using the computer for fun. Would that college student know? I had an opened roll of Life-Savers in my pocket. I took it out, used my front teeth to free a cherry life-saver from the roll, and waited.

When I got the print-out, the output looked like this:

                           *
                                 *
                                      *
                                         *
                                          *
                                         *
                                      *
                                 *
                            *
                      *
               *
          *
     *
  *
 *
  *
     *
          *
               *
                     *
                            *
                                 *
                                      *
                                         *
                                          *
                                         *
                                      *
                                 *
                            *

I made art from math! I smiled to myself, packed up books and printouts, and went home.

* * *

This memory is from a long time ago, so I may have mis-remembered some details. If you want to see what an equivalent program in Python looks like, it follows here. On a Mac, run the Terminal application and type in the following:

python

This should appear:

Python 2.7.10 (default, Feb 22 2019, 21:17:52) 
[GCC 4.2.1 Compatible Apple LLVM 10.0.1 (clang-1001.0.37.14)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>

Type the following, including spaces:

import math
incr = math.pi / 10
x = 0.0
while x < math.pi * 4:
    x = x + incr
    y = math.sin(x) * 20.0 + 22.0
    print " " * math.trunc(y) + "*"

If nothing is happening, hit return again.

Saturday, December 9, 2017

WHY do Dependency Injection?

Many people have blogged on how to do dependency injection (DI), but few tell you why to use it.

What is dependency injection? It is the practice of passing objects that a class or method depends on, into the object or method, instead of the class or method creating that object itself.

Why use it? The purpose of dependency injection is to create a design for your code that is (a) testable, (b) separates responsibilities, and (c) is more flexible.

If your class or method creates objects and uses them, it could be argued that your code has too many responsibilities: creating objects is a difference responsibility than using them. That's a design argument for using DI.

If your class or method creates and uses objects it depends on, that makes unit testing it more difficult because your tests can't control or mock out those objects. This is the testing argument for using DI.

If your class or method creates and collaborates with objects it depends on, that makes re-using it to collaborate with different objects more difficult. This is the flexibility argument for using DI.

There's a nice description of using DI with Swift here:  https://cocoacasts.com/nuts-and-bolts-of-dependency-injection-in-swift/


Friday, October 20, 2017

How can we create an operator to append a value to an array?

This is a sample from my book in progress at LeanPub: What Every Programmer Needs to Know About Swift.

Sometimes you want to be succinct and repetitive — as in appending values to an array. We could create an operator function that modifies the array, but that doesn’t let us use the operator multiple times in the same expression. This is because the temporary values you get in a complex expression are immutable.

precedencegroup AppendPrecedence {
    associativity: left
    lowerThan: TernaryPrecedence
}

infix operator «: AppendPrecedence

func « <T>(lhs: Array<T>, rhs: T) -> Array<T>
{
    var result = lhs
    result.append(rhs)
    return result
}

let x = [1,2,3,4]
let z1 = (x « 5) « 6
print(z1) // prints [1, 2, 3, 4, 5, 6]

let z2 = x « 5 « 6
print(z2) // prints [1, 2, 3, 4, 5, 6]

let z3 = x « 4 + 5 * 9 « 12
print(z3) // prints "[1, 2, 3, 4, 49, 12]"

let z4 = x « 4 < 5 ? 22 : 33 « 12
print(z4) // prints "[1, 2, 3, 4, 22, 12]"

By making the precedence of this operator less than one of the lowest precedences (TernaryPrecedence), we can mix other expressions and still get the results we expect. Though you should use parentheses to make complicated expressions more clear.

Tuesday, October 10, 2017

Playing With Compare And Closures

// playing with compare() and closures

import Foundation

print("actOn start")
let one = "1"
let two = "2"

func actOn(_ result: ComparisonResult
        ifLess: ()->Void
        ifEqual: ()->Void
        ifGreater: ()->Void ) {
    switch result {
        case .orderedAscending:
            ifLess()
        case .orderedSame:
            ifEqual()
        case .orderedDescending:
            ifGreater()
    }
}

actOn(one.compare(two), ifLess: {print("    string 1 < 2")},
        ifEqual: {print("    string 1 == 2")},
        ifGreater: {print("    string 1 > 2")})

actOn(two.compare(two), ifLess: {print("    string 2 < 2")},
        ifEqual: {print("    string 2 == 2")},
        ifGreater: {print("    string 2 > 2")})

actOn(two.compare(one), ifLess: {print("    string 2 < 1")},
        ifEqual: {print("    string 2 == 1")},
        ifGreater: {print("    string 2 > 1")})

print("actOn end\n")

print("switch start")

switch one.compare(two) {
    case .orderedAscending:   print("    switch 1 < 2")
    case .orderedSame:        print("    switch 1 == 2")
    case .orderedDescendingprint("    switch 1 > 2")
}

switch two.compare(two) {
    case .orderedAscending:
        print("    switch 2 < 2")
    case .orderedSame:
        print("    switch 2 == 2")
    case .orderedDescending:
        print("    switch 2 > 2")
}

switch two.compare(one) {
    case .orderedAscending:
        print("    switch 2 < 1")
    case .orderedSame:
        print("    switch 2 == 1")
    case .orderedDescending:
        print("    switch 2 > 1")
}

print("switch end\n")

print("compare start")

func compareComparable
>(_ expr1: T, _ expr2: T, ifLess: ()->Void, ifEqual: ()->Void, ifGreater: ()->Void ) {
    if expr1 < expr2 {
        ifLess()
    }
    else if expr1 == expr2 {
        ifEqual()
    }
    else if expr1 > expr2 {
        ifGreater()
    }
    else {
       assertionFailure("\(expr1) isn't < or == or > \(expr2)")
    }
}

compare(1, 2,  ifLess:     {print("    1 < 2")},
               ifEqual:    {print("    1 == 2")},
               ifGreater:  {print("    1 > 2")})

compare(2, 2, ifLess: {print("    2 < 2")},
    ifEqual: {print("    2 == 2")},
    ifGreater: {print("    2 > 2")})

compare(2, 1, ifLess: {print("    2 < 1")},
    ifEqual: {print("    2 == 1")},
    ifGreater: {print("    2 > 1")})

// trigger assertion (as designed)
compare(Double.nan, Double.leastNonzeroMagnitude, ifLess: {print("NaN < n")},
    ifEqual: {print("    NaN == n")},
    ifGreater: {print("    NaN > n")})

print("compare end\n")



----------- output -------------------------------------------------------

actOn start
    string 1 < 2
    string 2 == 2
    string 2 > 1
actOn end

switch start
    switch 1 < 2
    switch 2 == 2
    switch 2 > 1
switch end

compare start
    1 < 2
    2 == 2
    2 > 1
fatal error: nan isn't < or == or > 4.94065645841247e-324: file forloop.playground, line 76


Saturday, October 7, 2017

How Do I Use "Switch" to Initialize a Variable or Constant?

This is a sample from my book in progress at LeanPub: What Every Programmer Needs to Know About Swift.

You might want to be able to use 'switch' to initialize a variable or constant, given 3 or more possible conditions (if it's just two, you can use the trinary operator ":?")
enum  Color {  // In this example, assume we can't associate 
    case red   // values with these cases _in_ this enum, perhaps
    case green // because we're not allowed to modify this code.
    case blue 
    case purple
}
let c = Color.green

// a one-line "switch expression" which doesn't exist in Swift.
let menuNumber = switch c { case .red: 1, case .green: 2, 
    case .blue: 3, default: 0 } // ILLEGAL SYNTAX
You can use a switch statement or if/else statements to initialize the value; the compiler knows you are initializing a constant within that logic. As long as in every code path before the constant is used, you initialize the constant once and only once.
let menuNumber : Int
switch c {
    case .red: menuNumber = 1
    case .green: menuNumber = 2
    case .blue: menuNumber = 3
    default: menuNumber = 0
}
print(menuNumber) // prints 2
You could also create a dictionary and subscript it in the same line of code:
// moral equivalent of a one-line "switch expression":
let menuNumber = [Color.red : 1, Color.green : 2, Color.blue : 3][c] ?? 0
print(menuNumber) // prints 2
We need "?? 0" because subscripting a dictionary returns an optional, which will be nil if the subscript value isn't found in the dictionary. The "??" operator returns the unwrapped value of the optional, if the optional isn't nil, and it returns the right-hand value, 0, if optional value is nil.
This is actually less code than "switch expression", but some people may find harder to read than the explicit logic of switch/if/else/etc. Use caution.

Wednesday, September 20, 2017

Is True Greater Than False in Swift 4?

This is a sample from my book in progress at LeanPub: What Every Programmer Needs to Know About Swift.

Is true > false?

Relational operators ("<", ">", "<=", ">=") are not defined for Bool values. So "true > false" is a syntax error.
However, if you want those operators to work with Bool values (so you can sort "false" before "true", for example), you canmake Boolean conform to the "Comparable" protocol. I'll illustrate:
extension Bool : Comparable {
    // "Is the left-hand-side value 
    // less than the right-hand-side value?"
    public static func <(_ lhs: Bool, _ rhs: Bool) 
            -> Bool {
        switch (lhs, rhs) {
            case (false, true):
                return true
            default: 
                return false
        }
    }
}

assert( (true  >  false) == true )
assert( (true  >= false) == true )
assert( (true  <  false) == false )
assert( (true  <= false) == false )
assert( (false >  true)  == false )
assert( (false >= true)  == false )
assert( (false <  true)  == true )
assert( (false <= true)  == true )
The Comparable protocol requires two operators be implemented: "<" and "==". It defines the other relational operators in terms of those two. I only need to implement "<", since Bool already implements "==".


Tuesday, September 19, 2017

What Every Programmers Needs to Know About Swift



I have a book in progress at LeanPub titled What Every Programmer Needs to Know About Swift.

I've set the minimum price to $0.00 for a while, so buying the book now is at no risk for you. (Plus, LeanPub has a money-back guarantee. See also their Terms of Service.)

This book is intended for people who already know a programming language and are getting started using Swift. Or, you may already know Swift, but have questions. Or, like me, you keep forgetting the syntax and you’re tired of searching the web and having to carefully read the pages you find to figure out which version of the Swift language some example code was written in. Plus, the page you find on the web might be wrong or long-winded.

My book is written for Swift 4, and every line of code has been tested in a Swift playground in Xcode. You should be able to copy and paste my code confidently.

It's in a question-and-answer format inspired by C++ Faqs by Cline and Lomow. (There are more recent C++ Faqs books on Amazon, which, if they are as good as the original edition, you should read if you’re programming in C++.

I'm also going to publish snippets from the book on my blog.

If you buy the book, please join and participate on the mailing list! (See the Introduction in the book.)


Saturday, April 29, 2017

Implementing Control Structures in Swift

In Smalltalk, control structures like "for" or "while" were not part of the language, but built using the language itself. The Smalltalk compiler would special-case these for efficiency, but you could make your own, if you wanted to.

In Swift, you can almost do the same, though the syntax makes it look less like native syntax.

I just wrote this in a Swift playground in Xcode 8.1.

NOTE: just because this is possible, doesn't mean you should do this. Readability and testability matters. This is just exploring the language.

import Foundation

extension Int {
    func through(_ end: Int, `do`: (_ i: Int)->() ) {
        var i = self
        while i <= end {
            `do`(i)
            i += 1
        }
    }
    // originally, I thought of naming this 'to' but that's ambiguous
    // whether the loop executes using the end value or not.
}

print("through loop 12-15")

12.through(15, do: {i in print("\(i)")})

/* prints
 through loop 12-15
 12
 13
 14
 15
*/

print("through loop 1-5")

1.through(5) { index in print("\(index)") }

/* prints:
 through loop 1-5
 1
 2
 3
 4
 5
*/

extension Int {
    func upTo(_ end: Int, `do`: (_ i: Int)->() ) {
        var i = self
        while i < end {
            `do`(i)
            i += 1
        }
    }
}

print("upTo 12-15")

12.upTo(15, do: {i in print("\(i)")})

/* prints
 upTo 12-15
 12
 13
 14
 */

print("upTo 0-5")

0.upTo(5) { index in print("\(index)") }

/* prints
 upTo 0-5
 0
 1
 2
 3
 4
*/

/*

 It's much more readable if you use the built-in syntax:

*/

print("for 12 through 15")

for i in 12...15 {
    print("\(i)")
}

/* prints
 for 12 through 15
 12
 13
 14
 15
*/

print("for 0 up to 5")

for i in 0..<5 { print("\(i)") }

/* prints
 for 0 up to 5
 0
 1
 2
 3
 4
*/