Do you prefer to limit the number of parameters accepted by a single function/method, and if so, how do you handle situations where more data is needed?

TLDR; specific questions at the end of this msg


Along with one of our list-colleagues (a fellow graduate?survivor from the time of mainframe computers, monolithic programs, when "structured programming" was 'the latest new idea', and OOP[s] was one's exclamation upon making a mistake) we have been re-reading and discussing "Code Complete". It is 'an oldie, but a goodie', and Python progs may feel so-superior by happily looking-past various C*/Java-based ideas.

The chapter on "High-Quality Routines" covers a lot of (hopefully, to you) familiar ground, eg structural-decomposition, descriptive names, manageability, readability, reliability, changeability, isolating complexity, SRP, strong-cohesion, loose-coupling (and all the fun of the fair...).

A particular focus is "Parameter passing issues" - that the list as an whole presents a "consistent interface abstraction", that the parameters are in a sensible sequence (that it matches any other similar function signatures), and that assumptions are documented. The recommendation is that the list be <= seven parameters. [I have a recollection that someone else (?'Uncle Bob Martin') recommends <= three]

What should one do when a routine requires numbers of input values? Does Python's lack of "interfaces" let us down?


If we were going to be pedantic, then the quick-and-dirty way to reduce the parameter-count might be to use a collection, eg put a physical address into a named-tuple or list called "address" instead of passing "street", "town", "city", "postal_code", etc.

We shouldn't be childish when it comes to style-guides. If the data is as cohesive as the components of an address, we should define a class. Now we can pass a single instantiated-object, with style and flair!

However, the criticism of that idea is that it 'breaks' encapsulation - the parameter's routine now needs to know which data-attributes exist within the passed object - which is an example of close-coupling. Also, if instead of creating a new object, eg "address", we passed across a containing object, eg "person"; we might save ourselves some effort! Sadly, we would (likely) be passing loads of unnecessary data, possibly even in an insecure fashion.

Time for some compromise? How about we add a method to the "address" example-object, which is then passed to the routine? It can be called, and deliver the object's necessary attributes per the interface's spec. NB we can do this in Python because a function/method is a "first-class object"! Now our parameter list is shortened (hopefully to the recommended degree) - thus also the degree of "coupling" between the call-ing and call-ed routines, the data passed is minimised, and the communication across the interface clarified. That said, haven't we now built what other languages might call an "interface"?


Questions:

Is the idea of limiting the number of parameters passed across an interface a real concern or somewhat an affectation?

Is three, five, seven, ... a valid limit (or warning-signal)?

Do you have a personal or corporate style or 'standard' to limit parameter lists to seven parameters, or some other number?

Given that Python enables labeled arguments ("keyword arguments"), does the concern really only apply to 'us' in terms of numbers of "positional arguments"?

Why not simply create and pass a collection (to suit the 'standards committee') and be done. What's the big deal, don't have time to waste, bureaucracy (!)...

What about the similar Q+D solution using a class? After all, we could just as easily build an extraction-routine into the calling-class, which reaches into the passed-class for the data it needs - then we don't have to go to the other team to ask their 'permission'/agreement/cooperation or wait for them to build the requisite method!

Is passing a function as an argument a safe and valid way to do business, or is it 'showing off'?

Does the pass-a-function idea making testing easier (of both the call-ed and the call-ing routines) and might it make a change (eg adding another field) easier to manage in-future?

What do you do?


Refs:
Steve McConnell, "Code Complete", Microsoft Press, 2004.
--
Regards,
=dn
--
https://mail.python.org/mailman/listinfo/python-list

Reply via email to