TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Shitlist Driven Development (2016)

404 pointsby r4umover 4 years ago

36 comments

reader_1000over 4 years ago
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.
评论 #25435402 未加载
评论 #25438585 未加载
评论 #25434749 未加载
评论 #25434966 未加载
评论 #25432964 未加载
评论 #25435628 未加载
评论 #25438481 未加载
pbronezover 4 years ago
Here, a “shitlist” tracks existing uses of deprecated behavior within a large code base. It prevents new uses of deprecated behavior without disrupting legacy code. This is a temporary measure used to facilitate refactoring large code bases.
评论 #25431262 未加载
fduranover 4 years ago
This is a good example of &quot;Organization as Code&quot;, where you are trying to influence a non-trivial change (often &quot;cultural&quot;) by code.<p>Frequently it&#x27;s better to change behaviour this way than say, holding meetings and presentations.<p>A typical example is &quot;we want our developer to write more tests&quot; but there are few existing examples of test code to look at and when you write a test it takes forever to run, so you fix this by fixing the underlaying issues (which is bad or non-existing code), rather than making developers attend TDD presentations and just talking about a &quot;test culture&quot; for example.
评论 #25437393 未加载
dhosekover 4 years ago
If you don&#x27;t want people to use deprecated code, it&#x27;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.
评论 #25431742 未加载
评论 #25431133 未加载
评论 #25431096 未加载
评论 #25431301 未加载
DonHopkinsover 4 years ago
It&#x27;s better to use a Shiterator, which can yield pieces of shit on demand, lazily enumerate them just in time, and generate infinite streams of shit, instead of allocating all your shit up front, and having your shit together in one place.
评论 #25431107 未加载
评论 #25431679 未加载
评论 #25434567 未加载
评论 #25431130 未加载
codeulikeover 4 years ago
&#x27;Shitelist&#x27; would rhyme better with &#x27;Whitelist&#x27;
评论 #25430614 未加载
Jumzieyover 4 years ago
Brilliant. It&#x27;s a really good compliment to strangling certain parts of a large code base.<p>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.
评论 #25432107 未加载
评论 #25430183 未加载
WJWover 4 years ago
This is an excellent way of using your (hopefully) already existing testing and CI infrastructure to change a social problem into a technical problem. As we all know, technical problems are by far the easier of the two. :)<p>We used this technique to great effect at my previous day job, though under the more neutral name of &quot;ratchet&quot;.
评论 #25430055 未加载
Rafertover 4 years ago
The Ruby-based tooling has been released as open source: <a href="https:&#x2F;&#x2F;github.com&#x2F;Shopify&#x2F;deprecation_toolkit" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;Shopify&#x2F;deprecation_toolkit</a>
anonyglerover 4 years ago
This is accomplished at Google using the build system. Your visibility declaration tells the build system what&#x27;s allowed to depend on a piece of code.<p>When deprecating old code, you can shut that door with a whitelist and gradually force consumers to migrate.<p>I really like how code is managed at Google.
dhd415over 4 years ago
A similar kind of automated mechanism is required in distributed systems that allow for rolling upgrades. New functionality in upgraded nodes can&#x27;t break not-yet-upgraded nodes and legacy behavior in not-yet-upgraded nodes has to be tolerated in upgraded nodes but only until the entire system is upgraded and then it is prohibited. Doing this wrong results in some really hard to fix production states.
gitgudover 4 years ago
On a somewhat related note: One of the biggest things I&#x27;ve noticed is that simpler pieces of software are less likely to be deprecated, whereas complex codebases quickly become legacy and abandoned...
评论 #25430883 未加载
donatjover 4 years ago
In a similar vein but on a smaller scale we have a number of tests for deprecated behaviors in our application code, and whitelist the existing code based on serializing the file name, method name, and the ordered list of parsed token <i>types</i> of the method.<p>That way minor alterations like changing a string or numeric value don&#x27;t remove the method from the whitelist, but alterations to the logic of the given method require you to fix the issue while you&#x27;re in there poking around already to pass CI.
molssonover 4 years ago
We used a similar approach when we pushed to get -Werror enabled in a large C++ code base I worked on years ago.
Remagedover 4 years ago
For the Java Developers here, have a look at archunit. We use this to discourage certain behaviour but you can also use it to test and whitelist the usage of shitlist items =&gt; <a href="https:&#x2F;&#x2F;www.archunit.org&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.archunit.org&#x2F;</a>
bravuraover 4 years ago
A simpler hack is just to give deprecated methods unwieldly and obstreporous names like: `REMOVEME_old_function_name`
awinter-pyover 4 years ago
I love his specific examples.<p>&gt; Make sure that a certain datastore is only read from in a certain context ... Ensure fallbacks for all uses of a secondary data-store ... joins between tables that have no business being joined<p>I wish linters &#x2F; typesystems were extensible enough to do this kind of domain-specific checking. There&#x27;s a new generation of static analysis that&#x27;s much more focused on architecture or business rules and is less about code-in-the-small concerns like class methods or operator compatibility.
javier10e6over 4 years ago
As software goes, years later there is going to be a shitlist_v_1 (bad classes) and a shitlist_v_2 (very bad classes) and on and on
ChrisMarshallNYover 4 years ago
That&#x27;s a pretty good idea.<p>I think a key to doing large, multi-developer projects, is true modular design, with opaque APIs, and each module with its own project identity and lifecycle.<p>Not a particularly popular stance, as it means a lot more overhead in each project.<p>It does reduce the need for shitlists, though.
mcvover 4 years ago
Even in a single-team project, I&#x27;ve ran into the problem that I&#x27;m refactoring some old code while others keep adding to it. Some way to have to cause failing tests sounds like a great idea.
jbackusover 4 years ago
Another cool way you could do this: Ruby methods can ask for their caller_locations. They work like this:<p><pre><code> # Source $ cat example_for_hn.rb def foo bar end def bar baz end def baz (c1, c2) = caller_locations.first(2) puts &quot;Parent caller: &#x27;#{c1.label}&#x27; in &#x27;#{c1.path}&#x27;&quot; puts &quot;Grandparent caller: &#x27;#{c2.label}&#x27; in &#x27;#{c2.path}&#x27;&quot; end foo # Demo $ ruby example_for_hn.rb Parent caller: &#x27;bar&#x27; in &#x27;example_for_hn.rb&#x27; Grandparent caller: &#x27;foo&#x27; in &#x27;example_for_hn.rb&#x27; </code></pre> So, you could define a method decorating class method like so:<p><pre><code> module Shitlist def shitlist(method_name, whitelist) original_method = instance_method(method_name) undef_method(method_name) define_method(method_name) do |*args, &amp;block| call = caller_locations.first passes_whitelist = whitelist.any? do |label, file_pattern| call.label == label &amp;&amp; call.absolute_path.end_with?(file_pattern) end unless passes_whitelist fail &quot;Shitlisted method! Permitted callers: #{whitelist}&quot; end original_method.bind(self).call(*args, &amp;block) end end end </code></pre> and then extend classes with it to use the decorator:<p><pre><code> class Example extend Shitlist def not_on_shitlist qux end def baz qux end def qux puts &#x27;Only some methods can call me :)&#x27; end shitlist :qux, &#x27;baz&#x27; =&gt; &#x27;shitlist.rb&#x27; end </code></pre> If I run this example (full source: <a href="https:&#x2F;&#x2F;git.io&#x2F;JLOdV" rel="nofollow">https:&#x2F;&#x2F;git.io&#x2F;JLOdV</a>), the non-whitelisted caller throws an error:<p><pre><code> $ ruby shitlist.rb Only some methods can call me :) Traceback (most recent call last): 2: from shitlist.rb:44:in `&lt;main&gt;&#x27; 1: from shitlist.rb:25:in `not_on_shitlist&#x27; shitlist.rb:13:in `block in shitlist&#x27;: Shitlisted method! Permitted callers: {&quot;baz&quot;=&gt;&quot;shitlist.rb&quot;} (RuntimeError) </code></pre> ---<p>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.
quickthrower2over 4 years ago
Got this T-shirt! It’s useful in regular sized code bases too. We used it for certain kinds of linting and code style errors.
gwbas1cover 4 years ago
I&#x27;m more curious about how things like shitlists are implemented in different languages.<p>Most of my experience is C#, where calling deprecated code triggers a warning.<p>Considering that C# warnings will fail in CI, how would someone do a C# shitlist? Would it require some kind of #pragma, that would stick out like a sore thumb in a code review
评论 #25440006 未加载
评论 #25436281 未加载
评论 #25431641 未加载
评论 #25431293 未加载
mellosoulsover 4 years ago
To an extent this seems to be related to more general automated detection of refactor targets&#x2F;&quot;code smells&quot; (ironically) for which there exist tools already (e.g. linters indicated in the article) - I like this simple &quot;list&quot; approach though.
chapiumover 4 years ago
Love the concept, hate the name. To me this seems like the recycle bin concept. Allow the code to exist temporarily, but encourage permanent deletion. Perhaps a better name could be a &quot;screamlist&quot; or &quot;needstochange&quot; list.
评论 #25431503 未加载
Tade0over 4 years ago
I kept a personal shitlist in one project but it was rather a collection of &quot;worst practices&quot; - things I vowed never to do.<p>It was personal because the idea didn&#x27;t get a lot of attention when I brought it up.
closeparenover 4 years ago
We use Bazel’s visibility settings this way. More often for controlled beta rollouts than for deprecation, but same principle. You can make it a compile time error to import a package that isn’t for you.
评论 #25433884 未加载
csutil-comover 4 years ago
I love that C# supports deprecation as a language feature and allows to mark an obsolete method as only usable by other deprecated methods, which is the same as the shitlist approach here in the end
Uberphallusover 4 years ago
Shitlist driven migration&#x2F;refactor, maybe. If it&#x27;s <i>development</i> it means you&#x27;re always deprecating something and that&#x27;s a significant organizational smell.
评论 #25431085 未加载
weeboidover 4 years ago
Very difficult to sell something named &quot;Shitlist&quot;
评论 #25434466 未加载
baxtrover 4 years ago
In case you wonder what shitlist means:<p><i>&gt; “shitlists”: a whitelist of deprecated behaviour. Existing deprecated behaviour is OK and whitelisted.</i>
mleonhardover 4 years ago
The article shows ways to prevent new dependencies on your deprecated library&#x2F;service. This is half of the problem. The other half is efficiently removing the existing dependencies.<p>Your team could change the other teams&#x27; code to remove the dependencies. This is usually inefficient. You will waste time learning their code. They may drag out the code review process for weeks or months.<p>Some teams may refuse to accept your changes and use your service deprecation as political capital to demand more headcount. They may even lie to their managers and claim that the dependency deprecation is justification for a rewrite that they want to do.<p>There is a technical solution that can help with this social problem: AUTOMATICALLY EXPIRING DEPENDENCY APPROVALS. Configure your library to allow only existing systems to use it, and make them all break on a certain date. Then, instead of forcing the other team to move, they have to move or their build breaks. And if they want to delay turndown they must convince you to change your code. Without automatic expiration, they can delay turndown by simply ignoring you.<p>Some teams may wait for the dependency expiration, lie saying they didn&#x27;t know about the turndown, and then demand that you delay the turndown and give them more time. You can work around this with a two-phased turndown. First create a new version of the library that allows only existing clients. Give the library a hideous name so code owners will want to remove it. Example: Deprecated_LiBrArY_YoUr_BuIlD_WiLL_BREaK_oN_20200601_LOL_Were_sERIUS_YOLO_exxtensuns_COme_frun_SVP_DaniELs_OnLY. Then set the existing library to expire in a week and email all users. They can easily switch to the new hideously-named library and in the process acknowledge that they know that their build will break at the specified date.<p>TLDR: Use expiring white lists so you won&#x27;t get ignored. Rename your deprecated library to something hideous to motivate code owners to migrate away from it.
kenerwin88over 4 years ago
Such a great idea, thank you for sharing!
TeeWEEover 4 years ago
Much better to annotate those functions with @deprecated and allow running in &quot;deprecated allow mode&quot; and a &quot;deprecated fail mode&quot;...<p>Never use profanity in your code, nor in your comments. Lets keep things professional.
评论 #25431489 未加载
评论 #25431552 未加载
评论 #25431524 未加载
评论 #25431529 未加载
einpoklumover 4 years ago
One can&#x27;t always introduce a multitude of shitlists into different places in the code. This can impact performance and readability; and perhaps even more importantly - if the language used is not high-level with reflection capabilities, you will be counting on callers&#x27; participation in calling the semi-deprecated API with truthful &quot;usage key&quot; for looking up on the shitlist. Who&#x27;s to say nobody reuses authroized keys for expediency?
jensneuseover 4 years ago
I will probably remember Sirupsen forever for his move of breaking Golang projects by renaming his github username. This led to go modules freaking out because different project used different name casing for the dependency. He has a popular logging library and go modules are angry when you rename github usernames..
评论 #25431210 未加载
评论 #25432085 未加载