Skip to content

Instantly share code, notes, and snippets.

@ghsatpute
Last active June 9, 2020 07:14
Show Gist options
  • Save ghsatpute/94ab13204439c264915c934098c5b164 to your computer and use it in GitHub Desktop.
Save ghsatpute/94ab13204439c264915c934098c5b164 to your computer and use it in GitHub Desktop.
Problems with dynamic typing

This was an interesting issue I observed in the production code.

There was a utility method which used to form a ticket message with comments as below

    private buildShortDescAndComments(...)
        ...
        const ticketComments = {
            comments: comment,
            shortDescription: shortDesc
        };
        return ticketComments;
    }

And this method was being used somewhere and output was passed on to some other method

output = buildShortDescAndComments(...); 

ticketClient.createTicket(output.comment, output.shortDesc); 

Now, the author did silly mistake of using comment instead comments (can't blame him for that, we're all humans and we make sily mistakes). Now, in strongly typed languages, this code even won't compile. Or if you use map, the code will fail at runtime.

But here, the execution went successfull by failing silently. Now we didn't know that comments were not updating properly after long time. I had to spend quite a some time to find this needle in haystack (you might think this would be very easy, it might be easy (and stupid) once someone tells you) but I spend around a day going through the code and figuring out the difference of s.

Also, this probably could have been solved with consistent and proper naming but in practice people don't spend that much time on these things thus adding maintenance overhead.

I have a library called repository which has method add_user, get_user, update_user I'm using mockito library which is available in both Python & Java

In Java, I used to get hints when I type when(repository). on last dot, I'll get suggestions on methods that are available in repository but in Python, I don't.

I have to manually copy paste the method names and then complete the when condition. This is time consuming.

I understand that this happens because when I write when condition in Java, it can figure out the types but in Python because of dynamic typing it cannot. Problem probably could be with the IDE itself. Need to try it on some other editor such as VSCode.

I am using this library boto3, which probably "the" standard library for calling AWS APIs Before I call the API I need to create client of boto3 by running following command

boto3_client =  boto3.client(...)

Now, I don't what I need to pass to this method I have to either look at examples, or look at documentation (which usually does not cover many sceanrios) I can also, look at the method documentation but it's defined as below

 def resource(*args, **kwargs):
    """
    Create a resource service client by name using the default session.

    See :py:meth:`boto3.session.Session.resource`.
    """
    return _get_default_session().resource(*args, **kwargs)
  
  
def _get_default_session():
    """
    Get the default session, creating one if needed.

    :rtype: :py:class:`~boto3.session.Session`
    :return: The default session
    """
    if DEFAULT_SESSION is None:
        setup_default_session()

    return DEFAULT_SESSION

By looking at above scenario, it's not pretty much clear what parameters does it expect. And what are possible exception sceanrios Of course, this problem could easily get solved by using specific parameters but again even if someone has mentioned them by looking at code it's not clear what that parameter is for example

do_something(attributes): 
    pass

What is attribute? Is it a class? String? or dict?

Here problem can be solved partially by having proper naming but I see lot of production code where people least care about proper naming. In Dynamic typed languages, the more responsibility is on developer to name their variables so that they reflect the type easily.

I spent considerbale amount debugging this. I had to pass tuple and I was doing this

cursor.execute(query, (1234))

The parenthesis do nothing here. Even with parameter that gets passed is of type integer and not tuple The reason is being explained here https://bugs.python.org/issue2817 But I don't see this as intuitive.

Also, this issue passed the unit test case as I was writing under wrong assumption at both place. When I did actually ran the code I debugged and found this issue (or non-issue if you'd like to call it)

Incosistent behavior while using similar but different data structures. In this case, list and tuples

>>> d = ['a']
>>> type(d)
<class 'list'>
>>> t = ('a')
>>> type(t)
<class 'str'>

I paritially agree with the problem that mentioned in above link, i.e you won't be able to differentiate between parens used for mathematical prcedence, or a function call. But that's what the job of language designer is, to design a language in a such way that particular syntax doesn't have dual meaning that language cannot figure out which is which.

** Note ** : This one may or may not be related to dynamic typing I found this while looking at co-worker's code.

>>> d = {"a": 1, "b": 2, "c": 3}

>>> if "a" and "b" and "c" in d.keys():
	print ("True")

True

Now, here at first I thought this some new syntax because the "English-like" statement looks perfectly valid. So I tried to play around it a bit

>>> if "a" and "b" and "d" in d.keys():
	print ("True")

# This prints nothing. 	
>>> if "Hello" and "a" in d.keys():
	print("True")

True 

Then I got to learn Python's if considers every and condition as different; and my co-worker's intent was interpreted differently by Python. This can introduce potential bug when code looks right. But whatever your intention of writing it is not the same as defined by the Python.

In Java, you won't be allowed to add string in if condition

if ("Abc") {
        System.out.println("Hello");
}
// This will produce compiler error, instead of printing "Hello"

Of course, one might agree that you should know the language before coding in production. But IMHO, it's not possible to know all the nuances of the language (especially in the world of many languages and almost impossible if the language itself is quirky). Language is the tool, learning tool is necessary but that tool is not the ultimate goal. Delivering products is. In this case, it becomes very important that there should be least scope for ambiguity.

try:
cust_table.put_item(Item=company,
ConditionExpression=Attr('version').eq(previous_version))
except botocore.errorfactory.ConditionalCheckFailedException as ex:
print(ex)
# botocore.errorfactory.ConditionalCheckFailedException: An error occurred (ConditionalCheckFailedException) when calling the PutItem operation: The conditional request failed
# During handling of the above exception, another exception occurred:
# Traceback (most recent call last):
# File "/home/ganesh/code/vantage-trials-site-reassignment-service/createUser/src/test.py", line 45, in <module>
# except botocore.errorfactory.ConditionalCheckFailedException as ex:
# AttributeError: module 'botocore.errorfactory' has no attribute 'ConditionalCheckFailedException'
# Above method is thrown but I'm not sure which excpetion to catch

There is a code I want to work on which is as below

    Promise.all([...])
        .then((e) => {
            this.client.post(endpoint, parameter, (err, req, res, data) => {
                ...
            });
        })
        .catch((e) => {
            callback(e, null);
        });

I want to know what exception will be thrown by above code. I've spent around 2 hours finding what exception the above code can possible throw. Additionally, I would like to throw an error code from e, as it is typeless I have no way to find unless I decide to do extensive search on Google or do code search on Github.

This is one of the production code in one of the repo. This is working fine.

import * as restify from "restify-clients";
export class Rest {
    readonly client: restify.Client;
    ...
    
    client.post(...)

With package.json deps as follows

  "dependencies": {
    "restify-clients": "1.5.2"
  },

I wanted to test this code, so I extracted the code in test.ts in separate TypeScript, Node project. But when I run, it says Client is undefined.

Update: Turns out that class is non-existent and I've spent 2 hours finding it. This code is running in production for more than 2 years and today I find it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment