Re: Speculation about Dijkstra's primitives and how small each function should be
- From: Calum Grant <not@xxxxxxxxxxx>
- Date: Mon, 18 Aug 2008 18:11:06 +0100
Robert Maas, http://tinyurl.com/uh3t wrote:
Dijkstra took function calls (including passing parameters to
called function and collecting return values) for granted, treating
each as an atomic action, and then said that a newly defined
function must combine these atomic actions in only three ways:
- Sequence (which can involve dataflow: return values from early
calls feed into parameters to later calls)
- Decision (IF/THEN or CASE/SELECT/COND)
- Repeating loop with test for exit (WHILE or FOR or MAP; i.e. LOOP in CL)
This restriction formed the basis of structured programming and
functional programming (except that in functional programming
a fourth type of combiner is allowed: LAMBDA/CURRY).
Extreme advocates for the language 'Forth' decided that each 'word'
(corresponds to 'function' or 'procedure' or 'subroutine' or
'method' in most other languages)
must combine atomic actions in just one (1) of those three ways. If
you have something that uses two or more of Dijkstra's combiners,
then the function/word ought to be split into smaller functions/words
each of which uses just one (1) of Dijkstra's combiners.
But tonight I got a new idea: In a "smart system", there are
several "facts" which are "known" by the software and used within
the code that comprises the system. Perhaps there should be a
Dijkstra/Forth style restriction that each function must know at
most one fact. If you have a function that knows two (or more)
unrelated facts, that function ought to be split into separate
functions each of which knows just one of those facts. Furthermore
each fact must be known by just one function.
Note that if you have a dataset that contains a large number of
specific facts all of the same type, accessed in a uniform manner,
that entire set should be treated like a table in a relational
database: Each access method for that table/dataset should be a
single function. So a single access method for a whole set of
related facts in a RDBS or similar dataset counts as just one
"fact" per my proposed restriction.
What do y'all think of my idea?
Well if you are interested in managing "facts" then Prolog is a great
place to start. One of my favourite languages.
As for restricting the responsibilities of functions - in OOP there's a
principle of single responsibility, so each class/function has one
responsibility. E.g. if you have a class "egg_and_beans" then that's
two responsibilities and the class should be split into two. However if
you have a class "breakfast" then that's coherent, and can again be one
class.
The comment on classes could equally apply to functions. They should
have one clear responsibility to avoid confusion and maximise reuse.
I've philosophised about this "paradox" that classes can do more yet
have fewer responsibilities. I think it's because the level of
abstraction has been raised.
What constitutes a "fact"? You might need a hierarchical concept of
facts, which matches your levels of abstraction. But that's just
structured programming. The flip of decomposition is composition. You
might also need to combine facts in different ways, and you're back to
logic programming which can express such things nicely.
I'd draw you away from the idea of "facts", since unless you are doing
logic programming, you are really interested in the "purpose" of a
component, and functions do more than manage facts.
As for each function knowing one "fact", there's a related principle
called the "Law of Demeter" (LoD). As a guiding principle it's very
useful, but is probably too much work to observe strictly.
LoD states that functions should not make assumptions about the
internals of the objects it uses. It forbids code like
toaster.handle.depress() (since you shouldn't probe the specific
features of the toaster), and prefers code like toaster.toast(bread),
thereby pushing the implementation into the object providing the
functionality. Actually that makes sense, since a future toaster could
use a laser-beam to toast, in which case is doesn't have a handle, but
could provide a toast() method. LoD is designed to make code more robust.
Also you talk about functions managing facts, but facts can be stored as
well as computed. There's a great programming paradigm which I
particularly like, which has decomposition, and binds functions to data
at various levels of abstraction. It's called object-oriented
programming! ;-)
Cheers,
Calum
--
Calum Grant - http://calumgrant.net
.
- References:
- Speculation about Dijkstra's primitives and how small each function should be
- From: Robert Maas, http://tinyurl.com/uh3t
- Speculation about Dijkstra's primitives and how small each function should be
- Prev by Date: Re: Whats the best language to learn...
- Next by Date: Re: Code timing
- Previous by thread: Speculation about Dijkstra's primitives and how small each function should be
- Next by thread: Programming forum
- Index(es):
Relevant Pages
|