Algebraic Data Types 2019-08-30

By Max Woerner Chase

Presented without context:

def _conditional_update(obj, attrs_and_values):
    for key, value in attrs_and_values.items():
        if value is not None:
            setattr(obj, key, value)

...

class Product(ADTConstructor, tuple):
    ...
    def __init_subclass__(
        cls,
        *,
        repr=None,  # pylint: disable=redefined-builtin
        eq=None,  # pylint: disable=invalid-name
        order=None,
        **kwargs
    ):
        super().__init_subclass__(**kwargs)

        overrides = types.SimpleNamespace()
        # This is really gross, but it seems to work, and it reduces the
        # cyclomatic complexity, so it must be good!
        overrides.__repr = repr  # pylint: disable=protected-access
        overrides.__eq = eq  # pylint: disable=protected-access
        overrides.__order = order  # pylint: disable=protected-access

        _conditional_update(cls, vars(overrides))

I have a problem.

And part of that problem is blindly trusting code metrics because they're hooked up to a SaaS that serves up a badge.

I'm about ready to revisit the Mypy plugin like I think I mentioned, but the way I've responded to having the metrics move around in unfavorable ways in after I implemented Products has me thinking that right now I need to think about what "quality" means in the context of this code, and whether these GitHub badges are actually delivering anything helpful.

I believe what I should actually be trying to do is make it easy for people who aren't me to understand my code. And I haven't been doing that. For example, one common thing I've gone and done is, I've put tiny conditionals into functions and factored them out, because that makes most complexity metrics think my functions are straightforward. It's like, I'm acting like I'm tricking the rating service, but I'm really just cheating the code by splitting it up into chunks with a cyclomatic complexity of around 5.

On the other hand, I think the stack iteration concept came from similar attempts to grind out branches, and I actually like that. The core logic is confined to a tiny file, and all the code that consumes it has to do is typecheck... which I don't currently check, but it's possible in principle.

So, I guess what I think is that helpful abstractions might not always jump out at me, and maybe my focus should be on "Okay, does this part of the code make sense, and can I make simple changes that would improve it on that axis?"

Once I've dealt with that some, though, I'm almost certainly going to back out the changes I excerpted above, because that code is ridiculous.

In any case, to make improvements here, I can't rely on tools to tell me what to focus on. I'm going to have to rely on... my own judgment!

(Haha, I was legally a child when that video was posted over ten years ago. *crumbles into dust*)

Anyway, I don't have anything more for now. Good night.