Thursday, November 28, 2013

Notes on solving a Rubik's Cube 3x3

Top Layer

Second Layer

Third Layer Sergs B. Third Layer Video
  • Make cross (frur'u'f')
    • dot
      • frur'u'f' with any face
      • will lead to l shape
    • l shape 
      • frur'u'f' with one leg of l pointing towards you, and the other pointing to the right
      • will lead to line
    • line
      • frur'u'f' with line horizontal
      • will lead to cross
  • Align cross (ruur'u'ru'r')
    • two sides should be lined up
    • colors are on opposite ends
      • ruur'u'ru'r' hold with one color on front and one on back
      • will lead to colors at right angle
    • colors at right angle
      • ruur'u'ru'r' hold with one incorrect side on front and one on right
      • all four sides will be lined up
  • Place corners (l'uru'lur'u')
    • place corner piece in between the three correct centers, not necessarily correctly oriented
    • all corners incorrect
      • l'uru'lur'u' on any face
      • will lead to one corner correct
    • one corner correct
      • l'uru'lur'u' with correct corner on front right face
      • repeat once again.
      • will lead to Rotate corners
  • Rotate corners (ruur'u'ru'r'l'uulul'ul)
    • three corners incorrect
      • ruur'u'ru'r'l'uulul'ul with correct corner on front left
    • two incorrect corners on opposite corners
      • ruur'u'ru'r'l'uulul'ul with one incorrect corner on front right with top color facing right
      • will lead to two incorrect corners on same face
    • four incorrect corners
      • ruur'u'ru'r'l'uulul'ul with two corners incorrect with top color on front and back on the right face
      • repeat once again, will lead to two incorrect corners
    • two incorrect corners on same face with top color on front and back
      • ruur'u'ru'r'l'uulul'ul with two incorrect corners with top color on front and back on the right face
      • will lead to two incorrect corners on same face with top color on same face
    • two incorrect corners on same face with top color on same face
      • ruur'u'ru'r'l'uulul'ul with two incorrect corners on right
      • will correctly rotate the two corners

Tuesday, November 12, 2013

The Curse of the Toxic Peer Review

A peer review system is meant to do two things:
  1. disseminate knowledge and understanding of how a new module works
  2. help train the developer group as a whole on what the best practices are for the development team considering that best practices are expected to evolve over time.
It IS NOT meant to be a tool used by the authority-needy to impose their judgements for the day's set of finished code.  If one single person on a team of 3 or more does all of the pr's, then you are doing it wrong.  If the rest of the team feels that they need to run pr past a single person, you're doing it wrong.  For the code being pr'ed, if individual teammates are not able to independently come up with the same set of criticisms, you are doing it wrong.  If there are no clearly stated requirements and standards of good code, you are doing it wrong.  If your junior members do not seem to be understanding what is required of them in order to get their pr merged into the development branch without completely rewriting the code, you're doing it wrong.

There are also requirements for who can do pr's.  It is expected that those doing pr's know the code base they are working in and know what is expected from them when writing code in the particular language.  A developer who is uninformed and unable to demonstrate understanding as to what the current developer group standards are should not be doing pr's.
  • Why are setting up a peer review system?
    • Do you know what you're looking for when code is submitted for review?
      • it's been linted
      • it has tests
      • you can run the tests and see that they pass
      • the documentation is sufficient to understand how to use the code without asking the author for more details/information
      • you understand how the code works and can demonstrate it
If you find yourself in the situation where you are the main person all PR's go to or if you feel that your teammates are not doing what you expect from them when they do pr's, it is YOUR job to discuss the situation with them and get on the same page across the team.

Considering that newer developers may not feel they carry enough weight to address a toxic peer review situation where a senior developer is in charge of all PR's, it is the manager's job to ensure that proper peer review policy is carried out.  If not handled properly, a peer review situation is not just useless, it's actually harmful in that it glorifies and deifies one or two developers to the point where a company feels it is completely dependent upon those individuals and behaves as if they are the saviors for the company.  This is not a good situation for any company to be in considering how fickle many developers are and the likelihood of any good developer sticking around for more than a year after an ipo is rather low.

You are trying to create a good product, you are trying to create a successful company. You owe it to your teammates and the rest of company to do more than simply wish that you could clone a particular developer.  You owe it to them to set up a proper peer review system such that information and understanding is spread across all developers in a team as easily as possible.

Sunday, November 10, 2013

Lemoncello

95.5% alcohol
10 zested lemons
750ml of alcohol
1000ml water
600ml sugar

75% alcohol
10 zested lemons
750ml of alcohol
750ml of alcohol
550ml of sugar



Zest lemons, put lemon zest into mason jar with alcohol for 1 month.
Stir the water and sugar in a large saucepan over medium heat until the sugar dissolves, about 5 minutes. Let Cool completely.
Strain lemon zest from alcohol.
Add alcohol to syrup.
Partition into 500ml bottles and place in freezer for 1 week.

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.

    Thursday, September 19, 2013

    Document your code.

    While programmers like to think they write code that anyone can look at and sort out, the painful reality is that code [even slightly complicated] can prove mystifying to other developers.

    -- Intro to Erlang O'Reilly book

    Saturday, August 10, 2013

    Riak $key index is slower than just get_keys..

    For riak 1.4 using leveldb as the backend so that secondary indexing is enabled via

    {riak_kv, [{storage_backend, riak_kv_eleveldb_backend},...]}
    {eleveldb, [
                 {data_root, "/var/lib/riak/leveldb"}
                ]}


    Data:

    from riak import RiakClient, RiakPbcTransport; ds = RiakClient('127.0.0.1',port=1030, transport_class=RiakPbcTransport)
    [ipython 11]: for x in xrange(1, 100000):
            ds.bucket('stuff').new('bob_'+str(x)
    ,
            data={'test_obj':x}).store()


    Setup:

    from riak.mapreduce import RiakMapReduce, RiakKeyFilter
    mr = MapReduce(self.datastore_client.riak_client)
    mr.add(bucket)
    mr.add_key_filters(RiakKeyFilter().starts_with(id_tag))

    b = ds.bucket('stuff')

     

    Results:

    [ipython 21]: %time max([int(_id.get_key().split('bob_')[1]) for _id in mr.run()])
    CPU times: user 4.09 s, sys: 0.31 s, total: 4.40 s
    Wall time: 40.94 s
          Out[21]: 99999

    [ipython 22]: %time max([int(_id.get_key().split('bob_')[1]) for _id in ds.index('stuff', "$key", ' ', '~').run()])
    CPU times: user 4.16 s, sys: 0.32 s, total: 4.48 s
    Wall time: 41.80 s
          Out[22]: 99999

    [ipython 23]: %time max([int(_id.split('bob_')[1]) for _id in ds.bucket('stuff').get_keys()])
    CPU times: user 0.48 s, sys: 0.01 s, total: 0.49 s
    Wall time: 1.39 s
          Out[23]: 99999


    Granted it's a super simple test, but the results are still confusing.  It could be a misconfigured leveldb?  Turning it on seems pretty basic.

    Wednesday, August 7, 2013

    Winpdb, awesome debugger.. needs emacs interface tho..

     After working with horrible php but the awesome xdebug+geben for emacs, I finally found an equivalent for python: winpdb and rpdb2.

    In your code all you need is

    import rpdb2; rpdb2.start_embedded_debugger('asdf',fAllowRemote=True)

    where 'asdf' is just some password you come up with so that other users can't start debugging on your code.

    Then start winpdb, navigate to file->attach, enter the password you chose, point it at your host and then debug away.

    Great!

    Tuesday, June 25, 2013

    Why use Python Properties?

    The reasoning is here, but in short  "...[t]he answer is, that in [a simple] use case we would not. In fact, we would write thus:
    >>> class MyClass(object):
    ...   x = 0
    ...
    >>> my = MyClass()
    >>> my.x = 4
    >>> my.x
    4
    

    'But!', I can hear you scream, 'there's no encapsulation!'. What will we do if we need to control access to x, make it read-only or do something else to it? Won't we have to refactor everything to the getters and setters that we avoided?

    No - we just switch to the property version, add whatever we want, and have not changed the interface one iota! The great thing about properties is not that they replace getters and setters, its that you don't have to write them to future-proof your code. You can start out by writing the simplest implementation imaginable, and if you later need to change the implementation you can still do so without changing the interface. Neat, huh?"

    Wednesday, May 29, 2013

    Python2's urllib2 is a miserable libary

    Python2's urllib2 is a miserable piece of shit of a library.  Use requests instead.

    Friday, May 10, 2013

    Install firefox 20 addons offline (via the command line)

    So much misinformation out there, that it took a while to figure this out.  And seeing that the documentation for mozilla firefox is an out-of-date mess, this will probably be out of date in a few versions as well.

    Currently the only way I've gotten an add-on to install automatically is as follows:

    1. Download the add-on.  You can simply go to the page for the add-on at https://addons.mozilla.org/en-US/firefox/ and right click on the 'Add to Firefox' button and select 'Save Link As...'
    2. Get the application id of the add-on and rename the .xpi file you downloaded to .xpi.  Typically the id is a uuid like {D4DD63FA-01E4-46a7-B6B1-EDAB7D6AD389}, but sometimes it's a string such as an email address or webaddress.  NOTE that if you have an id of {ec8030f7-c20a-464f-9b0e-13a3a9e97384}, you have the WRONG id.  That is the id for the firefox application itself (this value might change with different versions of firefox).
    3. Move the renamed xpi file to either your local mozilla profile directory at  ~/.mozilla/firefox/-profile_id-/extensions/ or to the global directory at /usr/lib/firefox-addons/extensions/. The -profile_id- can be found in ~/.mozilla/firefox/profiles.ini.  You'll have to find the correct Profile section and then the 'Path' for that profile (usually there's just one profile section, Profile0 with 'Name' = default).
    4. Restart firefox. You'll be prompted to install the add-ons you've added to the extensions directory once firefox starts up.
    The same can be done for themes.

    Monday, April 29, 2013

    Using the multi command in zookeeper to store objects larger than 1MB

    Quoting the third answer to the questions asked here.

    The idea would be that you would upload multiple pieces of the large object separately into different znodes (without using multi)

    Then you would update a pointer node that has references to the pieces while controlling for the version of the pieces (using a multi). 

    Friday, January 25, 2013

    Issues in python unittests using Python Mock

    In running some unit tests, my assertions were returning things like

    AssertionError: Mock name='mock.RiakClient().bucket().get().get_data()' id='39021008' != 'test-data'

    It does this because the object you are mocking doesn't have anything specified to handle the members that are being accessed on it.  That is if you have

    x = Mock()
    x.y = 'thing'


    but you call

    x.z
     
    Mock will intercept this and create a new mock object with the name 'x.z'.  You can string these along and get a name such as 'x.z.foo().bar()'

    The fix to my original issue (the AssertionError) is to simply handle the attribute correctly

    x = Mock()
    mock_get_data = mock(return_value='test-data')
    #one-liner
    mock_get = Mock(get=Mock(return_value=mock_get_data)

    #more readable two-liner
    mock_bucket = Mock()
    mock_bucket.bucket = Mock(return_value=mock_get)

    x.RiakClient.return_value = mock_bucket




    Edit: Added rest of mock object match the example better