Tuesday, October 29, 2013

Interview the interviewers

  1. Do you use source control?
  2. Can you make a build in one step?
  3. Do you make daily builds?
  4. Do you have a bug database?
  5. Do you fix bugs before writing new code?
  6. Do you have an up-to-date schedule?
  7. Do you have a spec?
  8. Do programmers have quiet working conditions?
  9. Do you use the best tools money can buy?
  10. Do you have testers?
  11. Do new candidates write code during their interview?
  12. Do you do hallway usability testing? (Joel test)
  13. Do you have a common development environment or other virtual image that has all the utilities developers share with each other?
  14. How is information about a new feature conveyed to other developers?
  15. Coding style - Compare and contrast
    •   if str == "str0": return 0
        elif str == "str1": return 1
        elif str == "str2": return 2
        elif str == "str3": return 3
        elif str == "str4": return 4
        elif str == "str5": return 5
        elif str == "str6": return 6
        elif str == "str7": return 7
        elif str == "str8": return 8
        elif str == "str9": return 9
    • dict = { "str0": 0,"str1": 1,"str2": 2,"str3": 3,"str4": 4,"str5": 5,"str6": 6,"str7": 7,"str8": 8,"str9": 9}; return dict[str]
    • answer 
  16. Python understanding
    1. Explain how `from module import other_object` works.  How is it different from `import module.other_object as other_object`?
    2. Given the following package structure:
      • package
        • __init__.py
        • sub_pkg_1/ 
          • mod1.py
            • test_class
            • test_function
          • __init__.py
        • sub_pkg_2/
          • mod2.py
          • __init__.py 
      • Which is more preferable:
        • from package.sub_pkg_1.mod1 import test_class; test_class()
        • from package.sub_pkg_1 import mod1; mod1.test_class()
        • import package.sub_pkg_1.mod1; package.sub_pkg_1.mod1.test_class()
        • Answer
      • Is `from package.sub_pkg_1.mod1 import test_class` faster because we are importing only the function that is needed rather than importing the whole module (which contains other functions/classes which python will waste time importing)?
        • Answer Importing the module doesn't waste anything; the module is always fully imported (into the sys.modules mapping), so wether you use import sys or from sys import argv makes no odds.
          The only difference between the two statements is what name is bound; import sys binds the name sys to the module (so sys -> sys.modules['sys']), while from sys import argv binds a different name, argv, pointing straight at the attribute contained inside of the module (so argv -> sys.modules['sys'].argv). The rest of the sys module is still there, whether you use anything else from the module or not.
          There is also no performance difference between the two approaches. Yes, sys.argv has to look up two things; it has to look up sys in your global namespace (finds the module), then look up the attribute argv. And yes, by using from sys import argv you can skip the attribute lookup, since you already have a direct reference to the attribute. But the import statement still has to do that work, it looks up the same attribute when importing, and you'll only ever need to use argv once. If you had to use argv thousands of times in a loop it could perhaps make a difference, but in this specific case it really does not.
          The choice between one or the other then, should be based on coding style instead.
          In a large module, I'd certainly use import sys; code documentation matters, and using sys.argv somewhere in a large module makes it much clearer what you are referring to than just argv ever would.
      • What is the difference between a package and a module? 
For the manager:

How do you handle the estimation process?
  • What I expect  - Time estimation should be at a level higher than the developers.  It is well known that estimations are always difficult. A simple estimation test should be enough to prove this. Managers should be keeping track of how long particular tasks a particular team to complete.  This is a TEAM based exercise, as the team as a group should be questioned as to the extent of difficulty for a particular task.  See Planning Poker.
How do you mange a developers time?
    • What I expect - It is a managers duty to maximize the amount of time a developer has to writing/thinking about code.  This means managing interruptions. There are scrum meetings that should be big and full of as many questions to satisfy any questions the manager as well as the questions from managers of other teams.  At any time other than the scrum meeting, all questions should be posted to the manager.  If they are unknown to the manager, then they can be brought up at the NEXT scrum meeting.  This ties into the question of "Do developers have quiet working conditions?", that are also free from context switches aka, interruptions.
    How do you manage the projects that are given to a developer?
    •  What I expect - "Good managers see their responsibility as removing obstacles so that people can focus on one thing and really get it done. When emergencies come up, think about whether you can handle it yourself before you delegate it to a programmer who is deeply submersed in a project." -- Joel Spolsky.  and "never let people work on more than one thing at once".

    Tuesday, October 22, 2013

    In python, [] and {} are dangerous default values

    In python, [] and {} are dangerous default values as noted at stackoverflow. A simple work around is to have query_args=None then do

    query_args = query_args or {}

    in the function code.

    If/else vs Dictionary

    For some reason the issue of using if/else statements vs dictionary maps pops up regularly here.  It shouldn't as there's no reason to use an if/else ladder vs using a dictionary.  The only argument that developers can give for always arguing for If/Else ladders is that they're easier to read and understand what's going on.  Given the redundant code and slower performance, this is purely a personal opinion than a viable reason to prefer If/Else statements over dictionaries.

    An excellent comparison of If/Else vs Dictionary is provided at StackOverflow.  To summarize, using a dictionary ...
    • is built-in
    • is pythonic
    • requires less boilerplate code
    • has O(1) complexity, compared to the if-else linear O(n) complexity
    There's even a profile script to compare if/else usage vs dictionary usage.

    ifs = []
    dict = []
    for i in range(60):
        string = 'str%d' % i
        ifs.append('  %sif str == "%s": return %d' % ('el' if i else '', string, i))
        dict.append('"%s": %d' % (string, i))
    
    print 'dict = {', ','.join(dict), '}'
    print 'def with_dict(str):'
    print '  return dict[str]'
    
    print 'def with_if(str):'
    print '\n'.join(ifs)
    
    print '''
    import timeit
    
    def test_dict():
        for i in range(60):
            with_dict("str%d" % i)
    
    def test_if():
        for i in range(60):
            with_if("str%d" %i)
    
    print 'dict:', timeit.timeit(test_dict, number=10000)
    print 'if:  ', timeit.timeit(test_if, number=10000)'''
    


    Assuming the script is named dict_perf_test.py, it's run as python dict_perf_test.py | python.

    On a basic Lenovo T430, it gives:
    
    dict: 0.429204940796
    if:   1.22928714752
    Dictionary mapping wins.