A new pattern to reduce switch hell

37 views
Skip to first unread message

Edward K. Ream

unread,
Apr 9, 2017, 12:26:47 PM4/9/17
to leo-editor
Initing the atFile read/write code is always going to be tricky, but perhaps not so tricky as it is at present.

A few days ago I rejoiced to eliminate the atAuto ivar, keyword args and related code.

A few minutes ago, I was tempted to add it back.  This is clearly a bad idea, for two reasons:

1. Switches should be as specific as possible.

In this case, the switch will be called, allow_undefined_section_references.

General switches may also be reasonable.  For example, a "toString" switch, when passed to any AtFile write method, will never create a "huh?" when I read it. Ditto for the at.toString ivar.

2. When possible, switches should avoid polluting function signatures.

This can be done using the following pattern:

    ivar= 'allow_undefined_section_references'
    setattr(self, ivar, True)
    try:
        << call the code that uses this ivar >>
    finally:
        delattr(self, ivar)

The following code will test this switch:

    if getattr(self, 'allow_undefined_section_references'):

I have never seen this Python pattern before, but here it makes sense. It does complicate the calling and "using" code, but the complications are minor. Crucially, the complications are localized. The new pattern simplifies the rest of the AtFile class, which need not be aware of this switch at all! Furthermore, this switch can be tested anywhere in the AtFile class.

This is a big win.  At present, various switches "infect" the signatures of too many methods. The infection spreads to the at.initCommonIvars, at.initReadIvars and at.initWriteIvars methods.

I suspect one or two other fairly mysterious switches pollute AtFile signatures. If so, I'll remove them and the corresponding 'huh?' they evoke in the reader. 

Edward

Edward K. Ream

unread,
Apr 9, 2017, 12:42:29 PM4/9/17
to leo-editor
On Sunday, April 9, 2017 at 11:26:47 AM UTC-5, Edward K. Ream wrote:

The following code will test this switch:

    if getattr(self, 'allow_undefined_section_references'):

 Oops:  This should be:

    if getattr(self, 'allow_undefined_section_references', False):

or more simply:

    if hasattr(self, 'allow_undefined_section_references'):

The more I think about this pattern, the better I like it.  The hasattr test clearly indicates that the switch is inited in a non-standard way.  A search for the ivar name will show where.  Long ivar names are better, because safer (less likely to collide with an existing ivar).

This is so good. The "setter" code in leo.plugins.importers.javascript.py can "coordinate" with at.putRefLine without change any other code in the AtFile class. There can never be the slightest "huh?" about what is going on.

Edward
Reply all
Reply to author
Forward
0 new messages