Live data from Hacker News

Shitlist Driven Development (2016)

sirupsen.com

71–80 of 148 posts

Re: Shitlist Driven Development (2016)

#71
post #52

Much better to annotate those functions with @deprecated and allow running in "deprecated allow mode" and a "deprecated fail mode"... Never use profanity in your code, nor in your comments. Lets keep things professional.

If you do the above, your prod servers will always run in "deprecated allow" mode because developers continue to use (and add new) deprecated functionality. That's what the article is attempting to tackle. Why not use profanity in code? We're all adults.

> Why not use profanity in code? We're all adults.

You just answered your own question there.

Re: Shitlist Driven Development (2016)

#72
post #4

Brilliant. It's a really good compliment to strangling certain parts of a large code base. As always the key is getting the information to the right people at the right time, and making it more difficult to make the wrong choices then the right choices.

Exactly. What's nice about this approach is it factors in the "behavioural economics" of developers. As the author puts it...

> At the end of the day, everyone needs to get work done, and if they see a code-path already being used from 10 places in the code-base despite these soft warnings–it doesn’t seem crazy to introduce another.

Even the best person with the best intentions will take a short cut under some circumstances, meaning to fix it later then getting distracted before that happens.

Re: Shitlist Driven Development (2016)

#73
post #66
post #25

If you don't want people to use deprecated code, it's essential to document what the replacement should be. In JavaWorld, this can be done through Javadoc. Just tagging a method or class with @Deprecated and leaving it there is the sort of thing that makes me want to hurt people.

Your comment made me think of the adage: "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live"

Another, less extreme version: "Your most important collaborator is yourself six months ago, and they won't respond to your emails."

Re: Shitlist Driven Development (2016)

#74

Earlier quoted context omitted.

That’s because you don’t understand what deprecated means. Deprecated means “still supported but its use is discouraged.” It does not mean “no longer supported.”

I've always understood Deprecated to mean "This works, but we don't want you to use it in new code, and we plan/hope to remove it in the future."

Deprecation without an obvious replacement is pretty toothless, because people will keep using the deprecated thing for lack of an obvious replacement. This is how we ended up with disasters like the Python 2/3 transition.

Re: Shitlist Driven Development (2016)

#76
Another cool way you could do this: Ruby methods can ask for their caller_locations. They work like this:

    # Source

    $ cat example_for_hn.rb
    def foo
      bar
    end

    def bar
      baz
    end

    def baz
      (c1, c2) = caller_locations.first(2)
      puts "Parent caller:      '#{c1.label}' in '#{c1.path}'"
      puts "Grandparent caller: '#{c2.label}' in '#{c2.path}'"
    end

    foo

    # Demo

    $ ruby example_for_hn.rb
    Parent caller:      'bar' in 'example_for_hn.rb'
    Grandparent caller: 'foo' in 'example_for_hn.rb'
So, you could define a method decorating class method like so:

    module Shitlist
      def shitlist(method_name, whitelist)
        original_method = instance_method(method_name)
        undef_method(method_name)

        define_method(method_name) do |*args, &block|
          call = caller_locations.first
          passes_whitelist = whitelist.any? do |label, file_pattern|
            call.label == label && call.absolute_path.end_with?(file_pattern)
          end

          unless passes_whitelist
            fail "Shitlisted method! Permitted callers: #{whitelist}"
          end

          original_method.bind(self).call(*args, &block)
        end
      end
    end
and then extend classes with it to use the decorator:

    class Example
      extend Shitlist

      def not_on_shitlist
        qux
      end

      def baz
        qux
      end

      def qux
        puts 'Only some methods can call me :)'
      end
      shitlist :qux, 'baz' => 'shitlist.rb'
    end
If I run this example (full source: https://git.io/JLOdV), the non-whitelisted caller throws an error:

    $ ruby shitlist.rb
    Only some methods can call me :)
    Traceback (most recent call last):
      2: from shitlist.rb:44:in `'
      1: from shitlist.rb:25:in `not_on_shitlist'
    shitlist.rb:13:in `block in shitlist': Shitlisted method! Permitted callers: {"baz"=>"shitlist.rb"} (RuntimeError)

---

Of course, you might not want this hijacked method with tracing inside something performance critical. You could always configure the implementation to be a no-op in production.

Re: Shitlist Driven Development (2016)

#77
post #62

Earlier quoted context omitted.

Prod should always be running in allow mode anyway for the same reason that prod builds compile out debug asserts and static type checks. Once the code passes review and makes it into prod you've already lost and spitting out warnings on every function invocation will just piss off your ops team.

Right. So what's the point of having @deprecated tags and a deprecated fail mode if you can't ever use it?

Tests.

Re: Shitlist Driven Development (2016)

#78
I don't remember the exact project or where I read it but one project added delay (using sleep function) to depreatected methods in order to discourage people using them. After every release, they increased the sleep time so that at one point it became impossible to use it without noticing it. Although I don't know if it is possible to do this for new code trying to use deprecated function and have old code use non-delayed one, I think it was a nice trick.
Post reply on HN