The Beauty of Decorators

@Decorator Pattern
@Python Wiki: Decorators
@Python Usage

Beautiful Code is being nice

“A set of rules? About Code? Decided by whom? Why? What about (…)?”

If “Beautiful Code” sounds a lot like (sometimes objectionable) social norms, it is because code beauty IS a social norm. Moreover, it is a social norm within a subgroup often reknown for being unsociable. When I started programming, code beauty was just something to ignore while I was “getting things done”.

Then I read “Clean Code”. Then “The Humane Interface”. Then I started reading other people’s code at work. It’s amazing how quickly I gained appreciation for social norms once they had vanished.

My mom once told me to “be nice”; I realized then that it was something I had to apply to code.

Some Features are not nice

The thing about using more involved language features is that I am always concerned the person after me won’t know them, or won’t readily adapt to them. For example, lambda functions are great for code locality, but in some cases, terrible for readability.

Moreover, the “magic” class attributes and functions are not always obvious to someone when they come to a language.

Example:

def get_login_user_info(user):
    if user.is_logged_in():
        with SqlConnectionClass() as conn:
            conn.execute("select foo from bar where ~~~~")

Someone unfamiliar with Python is going to come to this and be confused by parts of the syntax. The “with” statement has multiple “magic” class functions (”enter” and ”exit”) which are called when you run a function. Maybe a future programmer is going to read that as a class init and make some changes in init and get frustrated when conn does not necessarily return what they think should be returned. At this point, they will look up the details on Stackoverflow, and hopefully get familiar with “context managers”.

An educated person shouldn’t necessarily hold back due to the needs of an ignorant person. However, I can see the potential confusion that may arise if this pattern continues. having multiple contexts make it visually unclear where and when they end; moreover, this function has multiple roles, some of which should be stripped out and used across many different functions.

PyCharm helps with the confusion, but I think there is a better way.

Decorators Make Things Beautiful

“…we need to make sure that the statements within our function are
all at the same level of abstraction.” – Robert C. Martin

Decorators make things easier to understand.

Example:

decorators.py

def user_login_required(fn):
    def validate_login_fn(*args, **kwargs):
        if "user_id" in kwargs and "password" in kwargs:
            if check_login(user_id=kwargs["user_id"], password=kwargs["password"]):
                return fn(user_details=get_details(kwargs.get("user_id"), *args, **kwargs)
            raise ValueError("Invalid user_id or password")
        raise KeyError("You must pass the user_id and password as keyword arguments")
    return validate_fn

def db_cursor_required(fn):
    def add_db_cursor(*args, **kwargs):
            # Automatically closes the connection when the function finishes executing
            with SqlConnectionCursor() as cursor:
                # Automatically closes the cursor when this closes.
                with cursor:
                    return fn(cursor=cursor, *args, **kwargs)
        else:
            return fn(*args, **kwargs)

    return add_db_cursor

db.py

@user_login_required
@db_cursor_required
def get_user_foobar(*args, **kwargs):
    return kwargs["cursor"].execute("select foo from bar where ~~~~")

main.py

get_user_foobar(user_id="Foo1", password="")

This significantly more readable.[1] A DB Connection is required. A User Login is required. All aspects related to both are dealt with directly in the decorator function, ensuring the same level of abstraction throughout. You never have to deal with the mental overhead of remembering login functions and the related etails.

[1] Yes, the decorator functions themselves are complicated, but they are destined to be heavily-tested building-blocks for your application. As a result, you can also put in more strenuous (read: less readable) data checks within the login code; as you only have it in one place, it isn’t asking too much to learn it once, as opposed to learning it over and over again.

Incidentally, adding in another layer is not necessarily difficult either, although it may change the variables you need to pass the function.

db.py

@user_login_required
@memcache_check
@db_cursor_required
def get_user_foobar(*args, **kwargs):
    return kwargs["cursor"].execute("select foo from bar where ~~~~")

Decorators are Nice

The first rule of functions is that they should be small. The second
rule of functions is that they should be smaller than that. – Robert
C. Martin

 

I firmly believe that learning a code base becomes easier with decorators, for many reasons.

  1. Decorators enforce consistency; you always pass “user_id” and “password” (for example); not doing so raises an exception.
  2. Decorators force you to use keyword arguments; I ALWAYS find them significantly more readable than the lack. (The people who argue against that are usually highly skilled and experienced programmers – who have never had to follow a poorly designed application built by someone before them)
  3. There is a logical place to start “learning” the code; figure out the decorators, which are always going to be a major aspect of the setup of the code.
  4. Each function can concentrate entirely on one thing (in this case: performing the DB call). If the data being returned is incorrect, you will fix the get_user_foobar function. If the database is not connecting properly, you will fix the db_cursor_required decorator function. If the login data is not being perused correctly, you fix the user_login_required function.

If you never used decorators, or find functional programming to be needlessly complex or unwieldy, you may not “like” this. Dynamically modifying functions is not a cheap process either, computationally-speaking. However, I am sure you will agree that the end function is much smaller. If we can agree on a social contract based on simplifying code and making it easier to read, Decorator are necessary.

Using Custom Django Settings Files with Jetbrains PyCharm

When the Jetbrains site said one could not use custom settings files with PyCharm, I was concerned; until I realised the comment was more than 2 years old.  You CAN use custom settings files.

Basically, you need to manually set the “manage” file to your django-admin.py file, and make the following modification to the additional options.  You must also make sure to define the PythonPath within the Environmental variables.

After this, my server ran just fine.

Screen Shot 2013-11-13 at 15.18.10

Screen Shot 2013-11-13 at 15.14.15

Japanese Startups

I happened to run into the conversation about Japanese startups on Hacker News and on the BBC. A few stream of thought notes.

  • While it is great to see South Korea has come a long way, it has hardly “overtaken” Japan. If anything, the work environment is /worse/, especially when it comes to supervisors, work environment, family environment, etc…
  • I didn’t have to deal with hyper-critical fellow employees, but maybe it is a people skills problem.  We all know brilliant people who have difficulty expressing themselves appropriately..
  • Not very convinced by the foreigner opinion.
  • I dislike Sony for many reasons. However, they seem to be much better than Toshiba and the other mobile providers. The new Experia Z seems pretty cool.
  • Why is it that Japanese people featured in these kinds of articles seem to couch their criticism in broad language (in English), yet the same sorts of people give very nuanced and detailed critiques in Japanese? I am not accusing them of being two-faced, but I wonder if there are culturo-linguistic barriers? I do notice there are things I freely say in Japanese that I would never say in English and vice-versa, maybe the lack of an emotional resonance? (I do think some English-language criticisms of Japan are hampered by broad generalizations)
  • The lack of trust of younger Japanese is really poisonous and I have felt it before. This bullshit about the “Yutori Sedai” makes for good jokes, but it seems like a self-fulfilling prophecy.

Angry rant about Akihabara that I posted on TLUG

Sitting on the train, it is hard not to be inundated by desperate Yodobashi camera signs that tell you about the benefits of buying from a brick-and-mortar store. ?#3 on the list is a knowledgable staff. And they also had something about a wide variety of computers. ?You’d think that meant that in nerd-capital Akihabara, we could get a Linux laptop without much effort.

First, “wide-variety” is more-or-less Pravda-worthy Newspeak. Every store has the exact same models from the exact same manufacturers. ?The specs are all the same. ?The monitors are the same resolutions, the chips are 95% the same. ?With the exception of the Alienware laptops, there is no difference. ?Ok, that’s understandable; same underlying components after all. ?Let’s run with it.

However, the staff is _never_ knowledgable about _anything_ related to computer software. At the Dell store, I was informed by the salesmen that “Dell does not sell anything but Windows branded PCs”. ?(Android mobile phones? ?Linux server boxes? ?Project Sputnik for laptop-based developers?) ?At Yodobashi, I was told “Oh, we never had Linux computers”,?as they ushered me by Android (read: Linux)-branded touchpads.

If this is the world’s second or third largest economy in a world that is going to be dominated by information technology, given that most servers are running Linux, why is it so hard to stock a _single_ Linux laptop model in a store that is otherwise filled with generic boxes from the same companies? ?Even if preinstalled linux is a pipe dream, why can’t there be at least one person on staff who is knowledgable enough about PCs that *he could let me know which laptops have generally decent Linux support?

I can build my own desktop. ?However, it’s a different story with laptops and I am willing to pay extra as it is a business tool, not a god damn toy. ?Instead, Yodobashi Camera is playing commodity hardware chicken with Softmap and Yamada Denki.

*??There are no females in Akihabara PC stores. That is not very PC. ?Har har har.