Thursday, June 29, 2017

Eat That Frog- Obey the Law of Forced Efficient

I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the chapter ‘Obey the Law of Forced Efficient’:

There will never be enough time to do everything you have to do, but there is always enough time to do the most important thing.

What are my highest value activities?
You must be crystal clear about your highest value activities before you begin work.

What can I and only I do that, if done well, will make a real difference?
Your job is to be clear about the answer and then to start and work on this task before anything else.

What is the most valuable use of my time right now?
Your most powerful thinking tool for success is your ability to discriminate between one priority and another. Take a few minutes each day and fix this first.


Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Sunday, June 25, 2017

    VIPER: Interactor and Entity

    In this post, we will see interactor work and entity engagement with it. Currently we have not attached it with any kind of data, now we will load up some to data and try to show it in view which is all the way back to presenter.

    Use Case: Now we know about view and presenter, it’s time for Interactor. We want to see name of the person and the company in UIView. For that we have one JSON file which we will load. 

    Task: Implement interactor, implement file reader, read the file, convert data in to model, transform it as per view and show the details.
    Anticipated output:
    VIPER: Interactor and Entity

    Here is a JSON file as of now which we want to load and show the data.
    //JSON file
    [{
      "_id": "58f9a19680685a4e1e6d5016",
      "index": 0,
      "guid": "0b10fe86-a222-4ca5-a094-0082b7d4c1af",
      "isActive": false,
      "balance": "$2,107.15",
      "picture": "http://placehold.it/32x32",
      "age": 35,
      "eyeColor": "green",
      "name": {
       "first": "Bertha",
       "last": "Irwin"
      },
      "company": "COMSTAR",
      "email": "bertha.irwin@comstar.net",
      "phone": "+1 (806) 584-3949",
      "address": "303 Vermont Street, Concho, Arizona, 1707",
      "favoriteFruit": "banana"
     },
     {
      "_id": "58f9a196c020af14f6726d3a",
      "index": 1,
      "guid": "d1695e0f-2d05-465e-8e14-eca9ad64c426",
      "isActive": false,
      "balance": "$1,194.79",
      "picture": "http://placehold.it/32x32",
      "age": 30,
      "eyeColor": "green",
      "name": {
       "first": "Norton",
       "last": "Curtis"
      },
      "company": "RECRISYS",
      "email": "norton.curtis@recrisys.tv",
      "phone": "+1 (850) 571-3013",
      "address": "106 Bliss Terrace, Vandiver, Mississippi, 9292",
      "favoriteFruit": "strawberry"
     },
     {
      "_id": "58f9a196d46f3d10560759bd",
      "index": 2,
      "guid": "bf810ee3-3bc4-44e0-8056-3ac3815d2887",
      "isActive": true,
      "balance": "$2,259.39",
      "picture": "http://placehold.it/32x32",
      "age": 38,
      "eyeColor": "brown",
      "name": {
       "first": "Zamora",
       "last": "Weber"
      },
      "company": "PERMADYNE",
      "email": "zamora.weber@permadyne.co.uk",
      "phone": "+1 (929) 591-2437",
      "address": "787 Crystal Street, Williston, Wisconsin, 6408",
      "favoriteFruit": "strawberry"
     },
     {
      "_id": "58f9a196fe6014ff5fd07cb5",
      "index": 3,
      "guid": "e5cfcd2e-2911-4293-9a0f-3a53374ea1d9",
      "isActive": true,
      "balance": "$3,019.42",
      "picture": "http://placehold.it/32x32",
      "age": 25,
      "eyeColor": "blue",
      "name": {
       "first": "Barnes",
       "last": "Pickett"
      },
      "company": "RECRISYS",
      "email": "barnes.pickett@RECRISYS.info",
      "phone": "+1 (804) 532-3235",
      "address": "500 Milton Street, Nadine, Kansas, 8781",
      "favoriteFruit": "apple"
     },
     {
      "_id": "58f9a196361f66d65c9b39f8",
      "index": 4,
      "guid": "80ca8651-5edf-4d11-bb09-688f654ff3ad",
      "isActive": true,
      "balance": "$3,334.51",
      "picture": "http://placehold.it/32x32",
      "age": 33,
      "eyeColor": "brown",
      "name": {
       "first": "Cohen",
       "last": "James"
      },
      "company": "COMSTAR",
      "email": "cohen.james@comvene.name",
      "phone": "+1 (953) 454-3801",
      "address": "230 Lefferts Avenue, Navarre, Tennessee, 3443",
      "favoriteFruit": "strawberry"
     },
     {
      "_id": "58f9a19607f1cc3aafc21c5b",
      "index": 5,
      "guid": "df311b09-081c-4a31-b30f-a87700728244",
      "isActive": false,
      "balance": "$2,046.56",
      "picture": "http://placehold.it/32x32",
      "age": 32,
      "eyeColor": "green",
      "name": {
       "first": "Vanessa",
       "last": "Sanchez"
      },
      "company": "COMSTAR",
      "email": "vanessa.sanchez@magmina.biz",
      "phone": "+1 (877) 430-2487",
      "address": "665 Norfolk Street, Bawcomville, Kentucky, 8056",
      "favoriteFruit": "banana"
     }
    ]
    

    Now Here is an interactor class:
    class Interactor: NSObject {
        func findListData() {
            //Find data
            let file = FileReader();
            //We can set default argument in parms it self - a Swift feature
           // file.readJsonFile(name:"company", exten: "json")
            if let data = file.readJsonFile(name:"company") {
                let myArr:NSArray? = ParseData(aObject: data);
                if myArr != nil {
                    presenter?.foundList(aList: myArr);
                }
            }
        }
        //MARK: Model parse
        func ParseData(aObject:Any) -> NSArray? {
            let myArr : NSMutableArray = NSMutableArray();
            if aObject is NSArray {
                for  mydata in aObject as! NSArray {
                    let data = mydata as! NSDictionary
                    let mymodel : CompanyModel  = CompanyModel.init(fname: data.value(forKeyPath:"name.first") as! String, lname: data.value(forKeyPath:"name.last") as! String, company: data.value(forKey:"company") as! String)
                    myArr.add(mymodel);
                }
                return myArr;
            }
            return nil;
        }
        
    }
    

    Here is a file reader class:
    class FileReader:NSObject {
        func readJsonFile(name:String, exten:String="json") -> Any? {
            do {
                if let file = Bundle.main.url(forResource:name, withExtension:exten) {
                    let data = try Data(contentsOf: file)
                    let json = try JSONSerialization.jsonObject(with: data, options: [])
                    if let object = json as? [String: Any] {
                        // json is a dictionary
                        // print(object)
                    } else if let object = json as? [Any] {
                        // json is an array
                        // print(object)
                        return object;
                    } else {
                        print("JSON is invalid")
                    }
                } else {
                    print("no file")
                }
            } catch {
                print(error.localizedDescription)
            }
            return nil;
        }
    }
    

    To transform data in to model we have one company-model class:
    class CompanyModel : NSObject {
        var fName : String = ""
        var lName : String = ""
        var company : String = ""
        init(fname:String,lname:String,company:String) {
            self.fName = fname
            self.lName = lname
            self.company = company
        }
    }
    

    There are some changes which we have to do in order to show the data. In presenter class, we will replace “foundList” method with below code:
    func foundList(aList:NSArray?) {
            if(aList != nil) {
                userInterface?.reloadList(alist: aList)
            }
            else {
                userInterface?.showNoContenctView()
            }
        }
    

    Now we want to show name, in view It is divided in two partition First name and Last name.We will add one method which can return these two in a single entity. To do so we will add one function in a model class.
    var name : String { get {
            return "\(fName) \(lName)"
            }
        }
    


    Now here is a code for UIView:
    extension  ViewController: UITableViewDataSource,UITableViewDelegate {
        //MARK:- TableView methods
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return myArr!.count
        }
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: ListEntryCellIdentifier, for: indexPath as IndexPath) as! listCell
            let myData:CompanyModel = myArr!.object(at: indexPath.row) as! CompanyModel
            cell.title.text = String(myData.name)
            cell.companyName.text = String(myData.company)
            cell.selectionStyle = UITableViewCellSelectionStyle.none
            return cell
        }
        //MARK: ViewInterface implementation
        func reloadList(alist:NSArray?) {
            myArr = alist
            if myArr != nil {
                DispatchQueue.main.async {
                    self.listTableView?.reloadData();
                }
            }
        }
        func showNoContenctView() {
            let alert = UIAlertController.init(title: "VIPER", message: "No content to show", preferredStyle:.alert)
            let okAction = UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)
            alert.addAction(okAction)
            self.present(alert, animated:true, completion: nil)
        }
    }
    
    

    At this point of time there is no major code in presenter, now we will change the requirement and see how presenter could be used.

    Time for twist: We want to sort the data and show the list as per their company and want to show the balance.

    Anticipated output:


    VIPER: Interactor and Entity

    To do so we need to alter data in model, presenter and UIView:
    class model code change:
     init(fname:String,lname:String,company:String,balance:String) {
            self.fName = fname
            self.lName = lname
            self.company = company
            self.balance = balance
        }
    

    Here is a change in code of presenter:
     func foundList(aList:NSArray?) {
            let sortedArray:NSArray? = self.SortCompanyList(aList: aList)
            if(sortedArray != nil) {
                userInterface?.reloadList(alist: sortedArray);
            } else {
                userInterface?.showNoContenctView()
            }
        }
    //This function is used to sort the data as we require.
        func SortCompanyList(aList:NSArray?) -> NSArray? {
            let sortedArray: NSMutableArray = []
            if(aList != nil) {
                let listOfCompany:NSArray? = aList?.value(forKeyPath:"@distinctUnionOfObjects.company") as? NSArray
                if(listOfCompany != nil) {
                    for companyName in listOfCompany! {
                        let predicate = NSPredicate(format: "%K = %@", "company", companyName as! NSObject)
                        let filteredContacts = aList?.filtered(using: predicate)
                        if ((filteredContacts?.count)! > 0) {
                            let sortedDict = NSDictionary.init(object: filteredContacts!, forKey:companyName as! NSCopying)
                            sortedArray.add(sortedDict)
                        }
                    }
                }
                
            }
            return (sortedArray.count > 0) ? sortedArray : nil 
        }
    

    Now here is a code for UIView:
    extension  ViewController: UITableViewDataSource,UITableViewDelegate{
        //MARK:- TableView methods
         func numberOfSections(in tableView: UITableView) -> Int {
            return myArr!.count
        }
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
             let dictSection:NSDictionary = (myArr?.object(at:section) as! NSDictionary)
            return (dictSection.object(forKey:dictSection.allKeys.first!) as! NSArray).count
        }
        func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
            let dictSection:NSDictionary = (myArr?.object(at:section) as! NSDictionary)
            let title:String = " \(dictSection.allKeys.first as! String)"
            return title
        }
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: cListEntryCellIdentifier, for: indexPath as IndexPath) as! listCell
            //Fetch model
            let dictSection:NSDictionary = (myArr?.object(at: indexPath.section) as! NSDictionary)
            let myData:CompanyModel = (dictSection.object(forKey:dictSection.allKeys.first!) as! NSArray).object(at: indexPath.row) as! CompanyModel
            //Set model data
            cell.title.text = String(myData.name)
            cell.companyName.text = String(myData.balance)       
            cell.selectionStyle = UITableViewCellSelectionStyle.none
            return cell
        }
        //MARK: ViewInterface implementation
        func reloadList(alist:NSArray?) {
            myArr = alist;
            if myArr != nil {
                DispatchQueue.main.async {
                    self.listTableView?.reloadData();
                }
            }
        }
        func showNoContenctView(){
            let alert = UIAlertController.init(title: "VIPER", message: "No content to show", preferredStyle:.alert)
            let okAction = UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)
            alert.addAction(okAction)
            self.present(alert, animated:true, completion: nil)
        }
        
    }
    
    

    This is the end of second VIPER post, In next post we will explore router/wireframe code and  unit test case for the same app.

    Tuesday, June 20, 2017

    5 Levels of Leadership

    Find out more with this summary of John Maxwell's The 5 Levels of Leadership.

    Level 1: Position (This would mostly comes with job title, People follow because they have to.)

    Level 2: Permission (People follow because they want to. as you personally taking interest in every member, Why, What and How they work? and set them on level 1 by being their mentor.)

    Level 3: Production (People follow because of what you have done for the organization. You encourage Level 2 people to do and be with them.)

    Level 4: People Development (People follow because of what you have done for them. At this stage people at Level 3 should not need your strict mentorship, they can do it and can do it very well.)

    Level 5: The Pinnacle (People follow because of who you are and what you represent. At this stage people do it and Level 4 would watch them.)


    5 Levels of Leadership

    Leadership is an Action and its always on going, learning and growing process.
    View a quick talk on leadership

    Wednesday, June 14, 2017

    VIPER an iOS architecture

    I have been practicing VIPER architecture since one year and I found lots of ups and down while using it.
    In this blog I will try to explain and simplify VIPER architecture.
    Here are the two images which you could see when you search for VIPER architecture. 

    VIPER an iOS architecture


    VIPER an iOS architecture


    Both are almost same and right. It is on you and use cases that which one you could choose to use. We will use both images at various time as we proceed.

    Why VIPER?
    Most of the iOS Apps follows MVC pattern and since much of the application code cannot fit in model or view are ended up in ViewController which makes our ViewController the Massive View Controller. VIPER could focus to reduce the load of ViewController.
    Testing was never a major part of making iOS Apps and it is too difficult to test with various architectures but VIPER helps a lot in this area too.
    We can divide code on basis of functionality like login, register, view account etc.

    What is VIPER?
    Here what VIPER stands for:
    V-> View
    I-> Interactor
    P-> presenter
    E-> Entity
    R-> Router
    Here is a general diagram which helps you to understand the flow.

    VIPER Flow Diagram



    View: One super secret is Your View = ViewController class + Interface View. It is a passive and can request presenter to update itself. The presenter does not know about any existence of UI elements like UIButton or UILabel, but it maintains the content. Till now what you do in ViewController class is your View and we will practice to reduce its load so now on View Controller has to worry only about showing content. And other responsibilities we will pass to presenter, interactor and so on.

    Presenter: It consist the logic to drive the UI. And also handles the events passed by View and interactor. Lets explore this both using example.


    Use case: We have a ViewController and we want to show some content in the view, however this is our first step we do not have any content to show, so we would show only popup with no content.

    Prior code:
    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
                self.updateView()
        }
        func updateView() {
             var myArray:NSArray? = nil ;
            //now we would call web service or db method to load data so that myArray != nil
            if(myArray != nil) {
                //Do change to make it appropriate with regards to view, like change array into model - entity form.
            }
            else {
                let alert = UIAlertController.init(title: "VIPER", message: "No content to show", preferredStyle:.alert)
                let okAction = UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)
                alert.addAction(okAction)
                self.present(alert, animated:true, completion: nil)
            }
        }
    
    }
    

    After adding presenter:

    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
                presenter.updateView()
        }
        func showNoContenctView(){
            let alert = UIAlertController.init(title: "VIPER", message: "No content to show", preferredStyle:.alert)
            let okAction = UIAlertAction.init(title: "OK", style: UIAlertActionStyle.default, handler: nil)
            alert.addAction(okAction)
            self.present(alert, animated:true, completion: nil)
        }
    
    }
    class Presenter:NSObject {
        func updateView() {
            //ask interactor for data.
            interactor.findListData()
          }
       
        //This method will be called by interactor once interactor gets the data
        func foundList(aList:NSArray?) {
            if(aList != nil) {
                //if list != nil //we would be doing some data formation before passing this to the view.
            }
            else {
                userInterface?.showNoContenctView();
            }
        }
        
    }
    

    Draft:1 This is the end of first draft, in next post we will learn about interactor and entity.

    Tuesday, June 13, 2017

    Eat That Frog- Focus On Key Result Areas

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the sixth chapter ‘Focus On Key Result Areas’:


    • Identify the key result areas of your work. 
    • ASK: What one skill, if I developed and did it in an excellent fashion, would have the greatest positive impact on my career?" Because, your weakest key result area sets the height at which you can use all your other skills and abilities. Your poor performance in the one key area can hold you back. 
    • The better you become in a particular skill area, the more motivated you will be to perform that function, the less you will procrastinate.


    Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Saturday, June 3, 2017

    Eat That Frog-Plan Every Day in Advance

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the second chapter ‘Plan Every Day in Advance ’:

    • How do you eat an elephant? The answer, of course, is “One bite at a time!”  
    • You break it down into specific step-by-step activities and then you start on the first one. 
    • Begin today to plan every day, week, and month in advance. 
      • Make your list the night before. 
      • A monthly list that you make up at the end of the month for the month ahead.
      • A weekly list where you plan your entire week in advance. 
      • Always work from a list. When something new comes up, add it to the list before you do it.  
    Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!

    Eat That Frog - Practice the ABCDE Method Continually

    I have read the book ‘Eat That Frog’, Here is a snippet that I could get from the fifth chapter ‘Practice the ABCDE Method Continually’:


    The ABCDE Method is a powerful priority-setting technique that you can use every single day. A tadpole should never distract you, when a big frog is sitting there waiting to be eaten. 


    1. "A" item is defined as something that is very important. If you have more than one "A" task, you prioritize these tasks by writing A-1, A- 2, A-3, and so on.
    2. "B" item is defined as a task that you should do. But it has only mild consequences.

    3. "C" task is defined as something that would be nice to do.
    4. "D" task is defined as something you can delegate to someone else.
    5. "E" task is defined as something that you can eliminate altogether. It is something you continue to do out of habit or because you enjoy it.

    Eat that Frog
    If you wish to purchase a book from AMAZON click here: http://amzn.to/2pnTEQB

    Have a great day ahead!