Software Development, Version Control

Collaborative Coding: Git and GitHub

New branch:
git branch [new branch name]

Checkout:
git checkout [branch name]

Checkout & new branch shortcut:
git checkout -b [branch name]

Add and commit to local:
git commit -am [“message”]

Push local branch:
git push -u [origin] [branch]

Feedback:
git status
git log

On GitHub open a Pull Request:

GitHub will analyse if it can be merged with no conflicts:

Add a reviewer and assign it to yourself. Add a label. You can also add it to a project or milestone:

Make a helpful comment on your pull request and create:

Once approved, your feature/bug/etc branch can be merged into the master branch:

Then your branch can be deleted:

That’s it! I hope this is helpful, my GitHub is linked below with the topic we’ve just discussed. I’ve also linked GitHub: Getting Started by Gill Cleeren with more information.

Standard
Language, Software Development

Clean Code: Meaningful Names

Key points on naming from Robert Martin’s Clean Code.

Intention revealing
The name of a variable, function or class should answer questions right away. What does it do, how you use it, why it exists, etc.

Avoid disinformation
Avoid leaving ‘false clues’. For example, don’t refer to a group of accounts as accountList unless the data structure really is a List.

Meaningful distinctions
Beware of using names which vary in small ways such as accountGroup and accountGroups.

Pronounceable
Pronounceable code can be read and understood much faster. It can also be discussed much more easily!

Searchable
Single-letter names and numbers are going to be hard to find. The length of a name should be appropriate for its scope, e.g. single letter names might be acceptable as local variables in small functions.

Class names
Classes and objects should have noun or noun phrase names like Customer, Account and AddressParser.

Method names
Methods should have verb or verb phrase names like postPayment, deletePage and save. Getters and Setters should be prefixed with get/set. Predicates should be prefixed with is.

Don’t be cute
Choose clarity over entertainment value. Is a tear-down function called eatMyShorts() funny? Of course! But it will be less of a headache in the long run to name it something more sensible and unambiguous.

One word per concept
Try to pick one word per abstract concept e.g fetch, retrieve, get.

Don’t pun
Use one word per concept, but within that avoid using the same word for different purposes. To use the same word for different ideas would be a pun. For example, say in our code base we have a lot of add methods that create a new value by adding two existing values together. Now we are making a new method that puts a single parameter into a collection. It might seem consistent to use add here again but as the semantics are different we should use a new term like insert or append to be clear.

Solution domain
Remember that the people that read your code will be programmers. So feel free to use technical ‘solution domain’ names like JobQueue because they will understand them. You don’t want to rely too heavily on business logic for names and have to run back to the customer for clarification. If there is no way of drawing the name from the solution domain, then you can go with the problem domain.

Meaningful context
Shorter names are generally better than longer ones, assuming they are clear.

That’s it! I hope this is helpful. I’ve linked Clean Code by Robert Martin if you’d like to get the book. Also ‘Uncle Bob’ is doing a lot of webinars at the moment including one on Clean Code so I’ve linked his website too.

Standard
Kotlin, Language, Software Development

Java to Kotlin

Main

Make a new Kotlin project, I’m using IntelliJ. In src make a main.kt file. Start with the equivalent main class as we would in Java. Declare a function with fun. Print Hello World. Notice you leave out the semi-colons. Note: when we don’t declare a class in Kotlin, the Kotlin compiler will generate one for you.

fun main(args: Array<String>) {
    println("Hello World")
}

Classes and Fields

Make an Employee.kt file. Declare an Employee class. Declare a field called name by using the var keyword. Declare it of type string. Fields have to be initialised in Kotlin so initialise it with an empty string:

class Employee {
    var name: String = ""
}

New

Now add to the main. Notice we don’t have to use the new keyword to instantiate an Employee:

    var employee = Employee()

String Interpolation

Kotlin will recognise ${} as string interpolation:

      employee.name = "Jack"
      println("My name is ${employee.name}")

Variables: Mutable or Immutable

Variables can be declared with var (mutable) or val (immutable). If we had declared name to be a val as below:

class Employee {
    val name: String = ""
}

Then it would be immutable, and we would get an error when we tried to reassign it in our main:

Constructors

Kotlin classes also support constructors. Change the Employee class so that it declares a constructor:

class Employee(var name: String) {
    //var name: String = ""
}

Now in the main class we can remove the below line:

    //employee.name = "Jack"

Instead we will pass “Jack” in the new Person constructor:

    var employee = Employee("Jack")

Public by default

The default access modifier in Kotlin is public. If we add a function to Employee:

    fun printEmployeeName() {
        println("Display: $name")
    }

We can call it from a different location:

    employee.printEmployeeName()

If / Else

In Kotlin If / Else can be used as an expression that will return a value. We can then assign that value to a variable:

    var message = if(employee.name == "Jack") {
        "Correct"
    } else {
        "Incorrect"
    }
    println(message)

Nulls

Kotlin tries to protect us against null values. It does that by requiring we explicitly state if something can take on a null value. In a new Question class we do that with a question mark to state our answer field might be null:

class Question {
    var answer: String? = null
}

In our main we can instantiate our Question like this:

    var q = Question()

Or if we want to state that our Question instance might be null we can do so:

    var q: Question? = Question()

If we had declared a Question instance that couldn’t be null we could have instantiated our answer like below:

    var q = Question()
    q.answer = null

However as we are declaring that the Question instance could be null if we instantiated it as above we would be prompted by the IDE:

To fix this we’ll use what’s known as the Safe Operator. The Safe Operator says if it evaluates to not-null then perform the operation, but if it evaluates to null don’t perform the operation. So add in the Safe Operator question mark:

    q?.answer = null

When statement

Instead of a Switch statement Kotlin has a When statement:

    fun printResult() {
        when(answer) {
            correctAnswer -> println("That's correct")
            else -> println("That's incorrect")
        }
    }

Try

Like If/Else, the Try statement in Kotlin is also an expression. Below are examples of its use, first with non-null input:

    var answerAsNumber: Int = try{
        Integer.parseInt(q?.answer)
    } catch (e: NumberFormatException) {
        -1
    }

And also with null input:

    var answerAsNumberNull: Int? = try{
        Integer.parseInt(q?.answer)
    } catch (e: NumberFormatException) {
        null
    }

Ranges

Ranges are a useful tool in Kotlin. You can have a range over anything that implements the comparable interface: integers, characters, etc:

    var myNum = 1..5
    var myChar = 'a'..'e'

    for (i in myNum) {
        print(i)
    }

    for (i in myChar) {
        print(i)
    }

Loops

While and do loops are quite similar in Kotlin. However For loops are slightly different. To iterate over a list:

    var numbers = listOf(1, 2, 3, 4, 5)

    for(i in numbers) {
        println(i)
    }

To iterate over a list and return the index:

    for((index, element) in numbers.withIndex()) {
        println("$element at $index")
    }

To iterate over a range:

    for(i in 1..10) {
        print(i)
    }

Ranges can be closed ranges, i.e. inclusive ranges. In Java we are used to a half-closed range. For Kotlin you can use a half closed range by using until:

    for(i in 1 until 10) {
        println(i)
    }

By using step we can define a step between the values:

    for(i in 1..10 step 2) {
        println(i)
    }

To iterate in reverse order, use downTo instead of ..

    for(i in 10 downTo 1) {
        println(i)
    }

To iterate over a map:

    var ages = TreeMap<String, Int>()
    ages["Tom"] = 23
    ages["Lisa"] = 43
    ages["Alex"] = 71

    for((firstName, age) in ages) {
        println("My name is $firstName and I am $age years old")
    }

Exceptions

Another thing Kotlin simplifies is the use of exceptions. For example if we look at the read method for FileReader, we can see in the SE 8 documentation it throws an I/O exception.

However in Kotlin we don’t have to catch or re-throw this exception. Kotlin essentially uses unchecked exceptions. This means we don’t have to specify that any class throws an exception and we don’t have to catch exceptions in Kotlin.

    var reader = FileReader("filename")
    reader.read()

That’s it! I hope this is helpful, my GitHub is linked below with the topic we’ve just discussed. I’ve also linked Kotlin Fundamentals by Kevin Jones with more information.

Standard