Connascence of Value

Connascence of value is when several values must change together. This frequently occurs between production code and test code. For example, consider an Article class, which represents a blog article. When it is instantiated, it is given some text contents, and its initial 'state' is 'draft':

class ArticleState(Enum):
    Draft = 1
    Published = 2


class Article(object):

    def __init__(self, contents):
        self.contents = contents
        self.state = ArticleState.Draft

    def publish(self):
        # do whatever is required to publish the article.
        self.state = ArticleState.Published

Now imagine a hypothetical test that ensures that the publish method works:

article = Article("Test Contents")
assert article.state == ArticleState.Draft
article.publish()
assert article.state == ArticleState.Published

The problem here is that the test requires knowledge of the initial state of the Article class: if the Article's initial state is ever changed, this test will break (this is arguably a bad test, since the first assertion has little to do with the intent of the test, but it's a common mistake). This code can be improved by adding an InitialState label to ArticleClass, and changing both the Article class and the test to refer to that label instead:

class ArticleState(Enum):
    Draft = 1
    Published = 2
    InitialState = Draft


class Article(object):

    def __init__(self, contents):
        self.contents = contents
        self.state = ArticleState.InitialState

The test now becomes:

article = Article("Test Contents")
assert article.state == ArticleState.InitialState
article.publish()
assert article.state == ArticleState.Published

Should we need to change the state machine of the Article class, we can do so by changing the ArticleState enumeration:

class ArticleState(Enum):
    Preproduction = 1
    Draft = 2
    Published = 3
    InitialState = Preproduction

We have effectively introduced a level of indirection between the Article class and its initial state value.