git.net

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Friday Finking: Limiting parameters


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