Search code examples
swift3indentationmultiple-languages

How to keep between 1 and 2 lines of indentation.


When reading the book 'Clean Code' by Robert C. Martin, he said that you should always try to keep between 1 and 2 levels of indentation. Three at a max.

Say if we have a dictionary (myDict) which is a type of [Int:[Int:[Int:String]]] (swift) and we want to loop through all the values, we would use a piece of code that goes:

for (key1, value1) in myDict
{
    for (key2, value2) in value1
    {
         for (key3, value3) in value2
         {
              //Do stuff
         }
    }
}

As you can see, the '//Do stuff' part is intented 4 times instead of being <=3.

How would i be able to make this code while staying at a maximum of 3 levels of indentation (preferably 1 or 2)?

Is this posible or not? I eould like the answer to be for all languages, however, if it is not posivle, could it be for Swift?


Solution

  • First realize that a nested dictionary has no advantage over a flat dictionary if all your data is only inside the deepest dictionary. So let's just merge our indices into one object:

    struct MyIndex : Hashable {
        let indices: (Int, Int, Int)
    
        init(_ index1: Int, _ index2: Int, _ index3: Int) {
            self.indices = (index1, index2, index3)
        }
    
        var hashValue: Int {
            return indices.2 // this should ideally use all the 3 indices
        }
    
        public static func ==(lhs: MyIndex, rhs: MyIndex) -> Bool {
            return lhs.indices == rhs.indices
        }
    }
    

    (by the way, this is exactly what IndexPath in UIKit is doing).

    Then we can just use our index instead:

    var dictionary: [MyIndex: String] = [:]
    
    dictionary[MyIndex(0, 0, 0)] = "test"
    dictionary[MyIndex(0, 1, 2)] = "test2"
    
    for (index, value) in dictionary {
        print(index.indices, value)
    }
    

    Instead of 3 nested for cycles, I am iterating the values all at once.