lines of code?

G

goose

Ok, then here is your challenge. Please provide a solution for the
following problem, not involving an additional thread:

iirc the spoke of kernel threads, not userland threads.
why are you mentioning java when it is obvious that NR was
talking about solutions involving *threads*, not solutions
involving java. also note that this is crossposted to
comp.programming, which is most definately *not* java-centric
(or any other language).

Mentioning "threads" in a conversation does not always mean
"java".
State of the Art:

When something happens in a Swing GUI (e.g. a button is pressed), a
corresponding event listener is invoked. The listener is always invoked
from the event-dispatching-thread (EDT). A Swing GUI freezes if one
blocks the EDT (does some time consuming tasks), because no further
event dispatching happens. Therefore time consuming tasks in response
to a GUI event have to be run in a separate thread.

Your Workarounds:

sure, tons, lots ... have done this plenty of times. they all involve
the select() function call and use C (or C++) for the implementation.

that was easy :)

since we were initially not talking specifically about java,
I think that that workaround is ok, no ?

no need for me to show any code, you should be able to easily figure
out what the system call select() on most unixen boxes would do.

goose,
who posts from comp.programming
 
M

Michael Borgwardt

goose said:
before you dismiss it totally, consider that:
a) I never mentioned any particular language.
b) Java threads can be user-land threads, and not always native
threads.
c) I was talking in the context of native threads.
d) multi-threaded programming with native threads which is
aimed at a single processor machine really *is* useless.

All of these points are completely irrelevant to the argument.
BTW, JVMs stopped using non-native threads years ago.

goose,
show me one good *generic* solution which /needs/ threads
on a single processor machine.

Not sure what you mean with "generic", but well, nobody strictly
/needs/ any programming languages other than assembler either.
Tell me, do you think that programming assembler on DOS allows you
to quickly write stable applications?
 
G

goose

Michael Borgwardt said:
All of these points are completely irrelevant to the argument.

I beg to differ. My original post is "complete nonsense" only if
I was designing a solution in java.

If I was designing in C, I would not need a thread library
to handle events. I would use the select() system call
available on all unixen and most (if not all) windows versions.

BTW, JVMs stopped using non-native threads years ago.

not all, esp the embedded JVMs
Not sure what you mean with "generic", but well, nobody strictly
/needs/ any programming languages other than assembler either.
Tell me, do you think that programming assembler on DOS allows you
to quickly write stable applications?

show me a solution, that is independant of programming language.
Use whichever /paradigm/ you want to. Any solution that you can show
me that isn't language-specific that /needs/ threads ? hmm ?

goose,
the problem, as I see it, is that solutions are designed
with a language in mind.
 
C

Chris Smith

goose said:
show me a solution, that is independant of programming language.
Use whichever /paradigm/ you want to. Any solution that you can show
me that isn't language-specific that /needs/ threads ? hmm ?

Sorry goose... I'm on Michael's side, and perhaps I can elucidate a bit.
It's, of course, possible to write many things without use of threads.
That doesn't make it a good idea. In the end, you end up with pro/con
decisions for specific situations in specific environments, and you make
a choice.

That said, there are a good number of factors suggesting the use of
multiple threads, which do not assume the presence of a multiprocessing
environment. Here's one:

Maybe I'm developing software that performs a number of rather involved
actions which are not batch-oriented (that is, they produce continuous
rather than single results, and there's consistent interaction with some
independent outside system such as a user, I/O peripheral, network
connection, etc. These actions need to all appear fairly continuous,
and threads provide a way to accomplish that.

The alternative? I could do them all in one thread. Yes, it would be
possible. However, if I were to do so, I would need the capability of
jumping back and forth from one task to another fairly frequently within
the same thread. If the actions are (to take one convenient example)
recursive algorithms, much of the current state of any one those actions
is going to be on the program stack at a given point. Without threads,
I have no way to save that state associated with the program stack and
temporarily switch over to another task.

Sure, I *can* express all these tasks as deterministic state machines,
moving the entire state of each task to external data structures, and
avoiding any use of the programmatic stack to represent the state of any
given action. What's beyond me is *why* I'd want to do so in many
situations. It's less natural and therefore more difficult and error-
prone, and it takes far more time and effort for another developer to
understand the work. When I have threads available, it makes sense to
use them if they solve my difficulties.

Sure, I might lose some possible performance. Do I care? Possibly not.
Quite possibly, it's more important for me to be able to easily write an
application that's capable of simultaneously interacting with several
live external entities than to squeeze every ounce of performance out of
the system at the expense of writing the whole software as a state
machine.

Now that's a huge class of applications of multithreading on
uniprocessors, right there. You can obtain specific examples by
choosing any set of live external entities. For example:

1. Interaction with user while printing.

2. Calculating data while transmitting results over a network in some
very involved transfer protocol.

, and the possibilities go on and on...

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
G

goose

Chris Smith said:
Sorry goose...

No need to apologise :) as you seem to have spent considerable
time crafting a well-thought out reply, I'll try to do the same
for you ...
I'm on Michael's side, and perhaps I can elucidate a bit.
It's, of course, possible to write many things without use of threads.
That doesn't make it a good idea. In the end, you end up with pro/con
decisions for specific situations in specific environments, and you make
a choice.

That said, there are a good number of factors suggesting the use of
multiple threads, which do not assume the presence of a multiprocessing
environment. Here's one:

Maybe I'm developing software that performs a number of rather involved
actions which are not batch-oriented (that is, they produce continuous
rather than single results, and there's consistent interaction with some
independent outside system such as a user, I/O peripheral, network

I'll keep the "network connections" example for later, as they are
all analogous anyway, but the network example is more or less
concrete, ok ?
connection, etc. These actions need to all appear fairly continuous,
and threads provide a way to accomplish that.

The alternative? I could do them all in one thread. Yes, it would be
possible. However, if I were to do so, I would need the capability of
jumping back and forth from one task to another fairly frequently within
the same thread. If the actions are (to take one convenient example)
recursive algorithms, much of the current state of any one those actions
is going to be on the program stack at a given point. Without threads,
I have no way to save that state associated with the program stack and
temporarily switch over to another task.

I'd agree with you ordinarily, but for the fact that you seem
to be ignoring that a multiple-threaded solution cannot (and
/should/ not) be implemented as a single thread. Your example
above illustrates the point rather nicely.

Your "alternative" to multiple threads is to "jump back and forth
from one task to another [in] the same thread". I'd suggest that
if your /solution/ demands multiple threads and/or tasks, then go
ahead and use it, but dont try to implement a multiple-thread
solution in a single thread. that just wont work nicely.

now that thats been said, taking the examples above, it would depend
on the environment. In an embedded environment, even if threads
*are* supported, I would not bother using multiple threads to do
io with user/network/other hardware. I'd set an interrupt, and use
it.

as an example with rs232 sending/receiving bytes on PC with no OS:
(forgive my psuedocode, I'm trying to keep it simple:).
a) interrupt handler:
needs two global arrays (rx_array, tx_array); also needs two
variables to index them (rx_index, tx_index). arrays are
circular arrays.
1. check which interrupt occurred (tx or rx).
2. if tx then
copy byte from tx_array[tx_index] to serial port;
increment tx_index;
if tx_array not yet empty,
enable tx interrupt.
else
disable tx interrupt.
3. else must be rx, so
copy 1 byte from serial port to rx_array[rx_index];
increment rx_index;
4. return.

b) serial_tx:
1. copy the argument/s into the tx_array (into appropriate place).
2. enable tx interrupt.
3. return.

c) serial_rx:
1. copy bytes from rx_array (from appropriate place)
2. return the bytes copied.

the logic is simple, innit ? the caller (user) merely calls
serial_tx and serial_rx, and the functions return almost
immediately, because serial comms is so slow. the caller
can be busy doing what ever else while the interrupt handler
does the work.

ok, so we dont use multiple threads in that embedded
environment, no ? but what about all the other environments ?

in a server environment, lets say a unix machine of some sort
(or even windows nt or better), you want to read from the
network *and* do user input ? no problem, use select() to read
from the network;

I suspect that the only case for multiple threads is to draw
bars (or twirling paddles) for the user in a GUI, although
given the right environment (MS-DOS anyone ?), this can be
easily achieved without resorting to multiple threads.

hell, if a webserver can "service" more than one request
at a time and *still* remain single-threaded, then the case
for multiple threads gets even weaker.

personally, what I *would* do is implement the select()
system call (if I can) on the target environment, and make
it be able to service anything.
Sure, I *can* express all these tasks as deterministic state machines,
moving the entire state of each task to external data structures, and
avoiding any use of the programmatic stack to represent the state of any
given action. What's beyond me is *why* I'd want to do so in many
situations.

its beyond me too. if your solution has more than one *task* that
simply *has* to run concurrently, then perhaps threads is your best
option.

however my rant was about coming up with a solution that involves
multiple threads merely because the environment offers it.
if one were to rethink a solution that involved multiple threads,
I would guess that most times a clean solution that does not
need more than one thread and/or task would be found.

the caveat of course, is that interrupt-driven io is much faster
than polled io.
It's less natural and therefore more difficult and error-
prone, and it takes far more time and effort for another developer to
understand the work. When I have threads available, it makes sense to
use them if they solve my difficulties.

Sure, I might lose some possible performance. Do I care? Possibly not.
Quite possibly, it's more important for me to be able to easily write an
application that's capable of simultaneously interacting with several
live external entities than to squeeze every ounce of performance out of
the system at the expense of writing the whole software as a state
machine.

the idea is not to squeeze every last bit of performance out of the
system, but to make it easier and simpler to understand. a single
thread of execution is *always* easier to read and then draw a diagram
off, especially if the code is all new to you.
Now that's a huge class of applications of multithreading on
uniprocessors, right there. You can obtain specific examples by
choosing any set of live external entities. For example:

1. Interaction with user while printing.

does not need threads, why poll the printer and/or user ?
simply use interrupts. If you are usnig an OS, the OS itself
will drive the printer while you are doing something else,
theres no need to set up a new thread to print.
2. Calculating data while transmitting results over a network in some
very involved transfer protocol.

does not need threads. I have already done this a few times,
with and without an OS.
if you have no OS, use the interrupts, if you have an OS
then simply send the data to the network and carry on with your
processing. while the data is being sent/packetised by the OS
for you, your code will run.
, and the possibilities go on and on...

but the only one that actually *needs* threads in order to
be designed elegantly is GUI code.
(and not even that, if your gui provides a select() or equivalent).

you see, even if your code is single threaded, the *OS* should
be able to schedule it properly. even though select() /looks/
single threaded, and behaves that way too, the OS will
do whatever threading it needs to in order to "multiplex"
(for lack of a better word) the execution.

goose,
interested to know exactly *what* solution can actually
use multiple threads of execution on a single CPU machine,
when there is already a premptive multi-tasking OS on the
machine.
 
P

Programmer Dude

goose said:
the idea is not to squeeze every last bit of performance out of
the system, but to make it easier and simpler to understand. a
single thread of execution is *always* easier to read and then
draw a diagram off, especially if the code is all new to you.

But sometimes the idea *IS* to squeeze every last bit out. (-:

Anyway, I just wanted to toss one more "use of threads" into
the hopper for you to shoot at.

Most browsers spawn threads to download the images of a page.
That solution seems simpler to me than any involving interrupts
or polling. One thread, one download.
 
N

nos

back in the early 1070's using PL/1 F on a 360/40 MFT
all you had to do was put the keyword "event" in the
statement that calls a subroutine and that subroutine
would be executed asynchronously, pretty easy
it was also very easy to tell if the routine completed
or to kill/stop it
and it didn't use no stinkin threads ;-)
 
S

Sudsy

nos said:
back in the early 1070's using PL/1 F on a 360/40 MFT
all you had to do was put the keyword "event" in the
statement that calls a subroutine and that subroutine
would be executed asynchronously, pretty easy
it was also very easy to tell if the routine completed
or to kill/stop it
and it didn't use no stinkin threads ;-)

And I wrote a Communications Transport Control Program
(CTCP) in GCS (see VTAM) for an X.25 gateway for an
X.400 e-mail product. It used multiple tasks in a single
address space. Thank goodness for the CS (Compare and
Swap) instruction! All written in Assembler G and with
PEP on the FEP.

Definitions for the newbies:

MFT: Multiprocessing with a Fixed number of Tasks
[as opposed to
MVT: Multiprocessing with a Variable number of Tasks]
VTAM:Virtual Telecommunications Access Method
PEP: Partitioned Emulation Program, allowing both
27XX EP and NCP on the same FEP
FEP: Front-End Processor (communications box)
NCP: Network Control Processor

Did we have some fun in the early days or what?!
 
G

goose

Programmer Dude said:
But sometimes the idea *IS* to squeeze every last bit out. (-:

of course, as a full-time embedded developer, I have to admit
that I normally *do* need to squeeze every last cycle out
of the processor into something usefull :)
Anyway, I just wanted to toss one more "use of threads" into
the hopper for you to shoot at.


Most browsers spawn threads to download the images of a page.
That solution seems simpler to me than any involving interrupts
or polling. One thread, one download.

very good example. I'll conceded that that example really
is one that could benefit from a multithreaded design.

(of course, a simple fork() system call could possibly
achieve the same result without using threads, but relying
on the OS to schedule your different tasks)


In my career, I've only once *needed* multiple threads for
my solution to a problem (although I've abused threads much more
than once). the "problem" was to ping every possible IP address
in the range X.Y.Z.1 to X.Y.Z.254. windows did not have (still
does not have, afaik) a fork() system call, so I spawned a thread
for each IP. then as each one came back, the thread stuffed the
return code into an array and ended.

If I were to do it on unix with bash, i'd write something
along the lines of:

#!/bin/bash
export COUNT=0
for X in `find /`;
do export COUNT=$(($COUNT + 1));
ping X.Y.Z.$COUNT && touch results/X.Y.Z.$COUNT &
if [ $COUNT -ge 255 ]; then
break;
fi
done
# to notify that it has finished.
echo -e \a


of course, this will return in a few seconds whether or not
each ping is finished, is *not* multithreaded PLUS you can
continue with your work and check later which IP addresses
are alive.

once again, the solution I *chose* above with bash did not
call for multiple threads because the environment allows
one to achieve the desired effect without the threads
(even though threads /are/ available). the windows design
*had* to use threads because at that time I had no idea
that windows command line proggys could be started with
"start /m", or that that command.com had a "for" statement
as well.

goose,
most browsers do indeed use threads; but is
that any endorsement ?
 
C

Chris Smith

Hi goose,

Thanks for your reply. If you don't mind, I'm going to simplify your
response by eliminating the part about embedded systems. That seems to
be your area, and the same ideas apply in either case... but I'm
guessing that for the majority of the readership, high-level libraries
such as UNIX select() and other means of async I/O are going to be the
way to go.
Your "alternative" to multiple threads is to "jump back and forth
from one task to another [in] the same thread". I'd suggest that
if your /solution/ demands multiple threads and/or tasks, then go
ahead and use it, but dont try to implement a multiple-thread
solution in a single thread. that just wont work nicely.

Just to clarify, we are talking about whether multithreading is ever
justified on a uniprocessor, right? That's what I thought we're talking
about. It sounds like you're saying that I should use multiple threads
in a server environment, lets say a unix machine of some sort
(or even windows nt or better), you want to read from the
network *and* do user input ? no problem, use select() to read
from the network;

That's making some assumptions about the problem that I was careful not
to make. Specifically, the goals I meant to discuss were intended to be
sufficiently involved as to require some degree of complex state on the
stack. I further intended that there be two fairly "live" goals
involved (and you'll notice that I mean something like "real-time", but
I'm being careful not to say real-time because I don't want to imply the
kind of substantial penalties for delay that are a connotation of that
term). So no, I'm not saying that threads are required every time a
network connection is used in an application.

Here's a very specific example:

Let's say I've got an application that reads some kind of TCP-based
streaming video protocol from one incoming network connection, performs
a transformation on it, and streams the resulting video out another
network connection. Both streaming protocols are rather involved,
requiring context-sensitive back-and-forth between client and server to
negotiate the data transfer rate and video characteristics required, and
the implementation of such a server ends up involving multiple levels of
recursion. The transformation itself may be simple, but the application
then has to implement the same very involved streaming video protocol
(from the other side) to retransmit the transformed data.

The problem with using select is this: every time you call select, it
might give you any amount of data in either direction. So you read
enough data to get seven deep in function calls in the streaming client
code, and then run out of available data. However, you *do* have a
frame available now to transmit to your *own* client, and you were also
waiting for available space in the buffer to do so. That space is now
available. Implementing the protocol to transmit that frame to the
client now is going to leave you five function calls deep in the
streaming server code. At that point, you want to return to receiving
data from your own source. How do you do that?

The only reasonable answer is that you rewrite those trasmit and receive
libraries so that they don't make function calls that will take time.
That means that you move their use of recursion to use of an explicitly
managed external stack, in conjunction with some kind of a deterministic
state machine to manage the protocol. Now, that's not a desirable
outcome: given a choice, most people would far rather read and
understand a top-down implementation of a context-ful network protocol
than a (state machine + external data) implementation. You are being
forced into the latter case by your choice to avoid multiple threads.
however my rant was about coming up with a solution that involves
multiple threads merely because the environment offers it.

Yet you continued to disagree when Michael and I both pointed out that
there are legitimate reasons for multithreading on a uniprocessor. Do
you agree with these legitimate reasons, or not?

Of course, in embedded systems, interrupts solve *some* of this problem,
exactly because they provide the ability to do some of what threads do:
interrupt an involved task, saving its entire state, and go do something
else. Even there, though, if the task to be done on the basis of the
interrupt is also involved and stateful, you run into problems because
the stack for the interrupt context is generally not preserved; so you
can deal with one stateful task + one interactive (non-batch) task, but
two tasks that are *both* stateful and interactive is still beyond you
without resorting to jmping through hoops to move the entire state off
of the program stack.
the idea is not to squeeze every last bit of performance out of the
system, but to make it easier and simpler to understand. a single
thread of execution is *always* easier to read and then draw a diagram
off, especially if the code is all new to you.

Reading the above, do you still agree? Is it really easier to
understand a single-threaded program that implements complex network
protocols as deterministic state machines? I would find that hard to
believe.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
G

goose

Chris Smith said:
Hi goose,

Thanks for your reply. If you don't mind, I'm going to simplify your
response by eliminating the part about embedded systems. That seems to
be your area, and the same ideas apply in either case... but I'm
guessing that for the majority of the readership, high-level libraries
such as UNIX select() and other means of async I/O are going to be the
way to go.

No problem.
Your "alternative" to multiple threads is to "jump back and forth
from one task to another [in] the same thread". I'd suggest that
if your /solution/ demands multiple threads and/or tasks, then go
ahead and use it, but dont try to implement a multiple-thread
solution in a single thread. that just wont work nicely.

Just to clarify, we are talking about whether multithreading is ever
justified on a uniprocessor, right? That's what I thought we're talking
about. It sounds like you're saying that I should use multiple threads
on a uniprocessor in some cases.

Nope. If your *solution* is *designed* as lots of seperate tasks,
then perhaps creating threads for each task is best. My contention
is that a lot of *designs* that calls for multiple threads
dont really get anything more than a single-threaded design would.

In other words, very many wizz-bang multi-threaded apps would be
no better in performance and ease of maintenance than single-threaded
apps (very often, there is a performance degradation for the multiple
threads).
If you're saying that, then perhaps I
just imagined the difference of opinion in the first place.
Nevertheless, you later said:


That's making some assumptions about the problem that I was careful not
to make.

but thats the example given (to do user input *and* read from a network
at the same time). Anyone who can do this *only* via the use of
multiple threads has missed something.
Specifically, the goals I meant to discuss were intended to be
sufficiently involved as to require some degree of complex state on the
stack. I further intended that there be two fairly "live" goals
involved (and you'll notice that I mean something like "real-time", but
I'm being careful not to say real-time because I don't want to imply the
kind of substantial penalties for delay that are a connotation of that
term). So no, I'm not saying that threads are required every time a
network connection is used in an application.

Here's a very specific example:

some clarification required. my comments below.
Let's say I've got an application that reads some kind of TCP-based
streaming video protocol from one incoming network connection, performs
a transformation on it, and streams the resulting video out another
network connection.s

a TCP-based protocol cannot, afaik, be "streaming". this is because
of the latency inherent in a connection-based protocol. perhaps some
protocol built on IP(UDP), which requires no virtual-circuit setup,
and no ack after X windows transmitted?

(sidenote: iirc, most, if not all, video/sound streaming protocols
*dont* use TCP, they use UDP).
Both streaming protocols are rather involved,
requiring context-sensitive back-and-forth between client and server to
negotiate the data transfer rate and video characteristics required, and
the implementation of such a server ends up involving multiple levels of
recursion.

I do not understand. the implementation of such a *server* ends up
involving multiple levels of recursion ? "recursion" is a design
decision. Are you certain you do not mean to say "protocol"
instead of "server" ?
The transformation itself may be simple, but the application
then has to implement the same very involved streaming video protocol
(from the other side) to retransmit the transformed data.

and here you say protocol. which do you mean, server or protocol.
The problem with using select is this: every time you call select, it
might give you any amount of data in either direction.
yes.

So you read
enough data to get seven deep in function calls in the streaming client
code, and then run out of available data. However, you *do* have a
frame available now to transmit to your *own* client, and you were also
waiting for available space in the buffer to do so. That space is now
available. Implementing the protocol to transmit that frame to the
client now is going to leave you five function calls deep in the
streaming server code. At that point, you want to return to receiving
data from your own source. How do you do that?

The only reasonable answer is that you rewrite

not "rewrite". if you had designed recursion in, then yes, you would
have to rewrite. if you had not, then no, theres no need to rewrite.

you took a design decision to *use* recursion, along with the pros
and cons of recursion in this particular example. as a result, your
design /needs/ multiple threads.

taking a design decision to use multiple threads, then showing
how difficult it would be to write the *same* design in a single
thread isn't very conducive to your argument :).
those trasmit and receive
libraries so that they don't make function calls that will take time.
That means that you move their use of recursion to use of an explicitly
managed external stack, in conjunction with some kind of a deterministic
state machine to manage the protocol.

if you are writing a protocol stack, a deterministic state
machine is unavoidable.
Now, that's not a desirable
outcome: given a choice, most people would far rather read and
understand a top-down implementation of a context-ful network protocol

I do not understand what you mean by this, in particular "context-ful".
given a choice when reading code for a protocol stack, I'll take
a state-machine over any other type of design any day.
than a (state machine + external data) implementation. You are being
forced into the latter case by your choice to avoid multiple threads.

nope. if you really are writing a protocol stack (no matter how
complex), then you really *should* be doing it with a state machine
anyway. what good is recursion if the other party hangs in a manner
that sends you recursing forever?

the only times I have seen protocol stacks implemented in a manner
/other/ than state machines is when the constraints required something
else (language being used did not allow pointers to functions,
protocol was too simple to require one, etc).
Yet you continued to disagree when Michael and I both pointed out that
there are legitimate reasons for multithreading on a uniprocessor.

Micheal, iirc, never pointed out anything: heres the relevant
posting (snipped irrelevant text):

---------------------------
I beg to differ. My original post is "complete nonsense" only if
I was designing a solution in java.
<snipped>
---------------------------

a few points to consider from the above post:
a) I should have qualified my statement about multiple
threads not actually buying you anything ("multiple
threads dont *always* get you anything more than
single-threaded", for example).
b) Micheal never pointed out that there were legitimate
reasons for using threads. his subsequent posts made it
very clear that his use of multiple threads was in the
context of java gui; I'm no java expert, but I am under
the impression that java is kinda useless if you cannot
have more than one thread; select() functionality has
only recently (2 years?) been added to java, no ?
c) In order for you (or Micheal) to justify the "this is
nonsense" response to my "does not buy you anything",
you would have to show that all multi-threaded design
is superior to single-threaded, i.e. you claimed it is
nonsense, now prove it. I've claimed that it does not
buy you anything, and I've given examples where it
did not buy you anything. You've[1] claimed that my claim
is nonsesnse, so now prove it.
d) I did not "continue to disagree", I only continued to
disagree that my post was "nonsense".
Do
you agree with these legitimate reasons, or not?

there are so few legitimate reasons for designing in
multiple threads, that even the example you gave could
possibly be redesigned to /not/ use multiple threads.

there *are* legitimate reasons, possibly one out of every
10 "solutions" designed with multiple-threads of execution
should really be multiple-threaded (or 1 out of every 100,
or 1 out of every 1000, etc ad nauseum). I've come across
at *least* 10 multi-threaded apps that /should not/ have
been multi-threaded, and only 1 that was legitimately so.
Of course, in embedded systems, interrupts solve *some* of this problem,
exactly because they provide the ability to do some of what threads do:

no, they provide entirely different functionality, for example, you
can be assured that an interrupt routine will run to completion (you
can't be sure of anything like that within a thread), will *never*
lose data as long as their is buffer space, will not be starved
if thread priorities change, etc.

a thread is a seperate but concurrent (to the programmer) path of
execution, an interrupt routine is not, even to the programmer.
interrupt an involved task, saving its entire state, and go do something
else. Even there, though, if the task to be done on the basis of the
interrupt is also involved and stateful, you run into problems because
the stack for the interrupt context is generally not preserved;

you had better clarify your usage of the word "stack". I dont understand
what you mean by that last sentence. the /stack/ on most machines
is not available anyway, all you have is scope for your variables.

what do you mean?
so you
can deal with one stateful task + one interactive (non-batch) task, but
two tasks that are *both* stateful and interactive is still beyond you
without resorting to jmping through hoops to move the entire state off
of the program stack.

once again, I dont know where you've gotten that idea. consider a small
program on an embedded chip (any embedded chip) with an embedded OS
(say ... uCOS). you want two "tasks" that interact with the user ?
no can do. if you do have two threads that both call display routines,
you are heading for a possible race condition (at best, at worst your
product will crash at crucial moments).

what you *should* do is either
a) have a seperate thread/task for display only. it sits in a
loop and displays stuff from a circular buffer (with control
codes if necessary). your other tasks will have to call a
display routine which will enter a critical section, add the
data to the buffer, exit the critical section and then return.

or

b) have all your various modules as state-machines. have a function
pointer to each one (lcd_state_machine, keypad_state_machine,
sio_state_machine, etc); at startup init all of them to start
states, then sit in a loop and run each state machine in turn.
things like sio will be interrupt driven anyway, lcd wont be.

I know which one can be *guaranteed* not to get deadlocked, or
cause a race: hint, its not a :).

this of course, is also applicable to large server development as
well. your protocol stack written with recursion will fall over
miserably the minute someone figures out the right bit of data
or header to repeat when talking to it, a state-machine otoh,
can easily tell if junk is coming along the way (although one
designed to loop states (pumping lemma) will hang not crash,
as it uses no extra resources like the stack does in recursion).
Reading the above, do you still agree?

I find the example above a rather nasty one for your argument. it
helps my argument more than it does yours :).

also note that I now clarify: there are very *few* legitimate
uses of threads. its up to you now to either say that my claim
is "nonsense", or to show so many legitimate uses of multiple-
threads that i cow and shiver in abject terror ;-).

(at least give 10 legitimate uses of threads, because right
now I can think of ten pieces of application software all
of which use threads, but find that only 1 of them has
what I would call a legitimate use of threads).

seriously though, I *have* given an example of a use of threads,
in another post in this same thread :)-), so you could not seriously
have been thinking that I decry *all* uses of threads. otoh, I got
the impression from you and Micheal (more from Micheal, to be honest),
that pointing at the fact that threads are needed so little is
a bit like insulting a mans wife. Micheal has not acknowledged
(and nor have you, for that matter) that a lot of thread-happy
designs need not be that way.
Is it really easier to
understand a single-threaded program that implements complex network
protocols as deterministic state machines?

yes. deterministic state machines have something going for them.
if you get the state-diagram right, you're 90% done. the complex
network protocol that is going to decode/encode the protocol with
recursive routines wont last too long; I'd be surprised if someone
did not figure out that he could slow the machine to a crawl if
he repeated the right data.
I would find that hard to
believe.


its not about belief;
goose,
the lawnmower man.
 
C

Chris Smith

goose said:
a few points to consider from the above post:
a) I should have qualified my statement about multiple
threads not actually buying you anything ("multiple
threads dont *always* get you anything more than
single-threaded", for example).

If that were what you'd said, I'd fully agree.
b) Micheal never pointed out that there were legitimate
reasons for using threads. his subsequent posts made it
very clear that his use of multiple threads was in the
context of java gui; I'm no java expert, but I am under
the impression that java is kinda useless if you cannot
have more than one thread; select() functionality has
only recently (2 years?) been added to java, no ?

It is correct that Java's APIs and language are designed around the
decision that threads are fundamental, so you're right in that respect.
On the other hand, outside of a GUI application, it's entirely possible
to write single-threaded Java applications today, even if they do I/O.
The fact that it wasn't possible prior to the release of 1.4 several
years ago is not very relevant these days.

The requirement for use of threads in a GUI environment mostly comes
from Java's lacking a way to "poll" for events and process them from
within a programmatic loop elsewhere in code. That polling method, so
well-known in VB, is clearly a broken idea in the first place. I would
not want to see a GUI application written as a single thread (though
such applications get written all the time in Microsoft VB environments,
and they generally prove how destructive the idea really is).

In the end, though, I don't personally think this question of
multithreading being "required" in Java is relevant, anyway. After all,
even if multithreading is forced in a few situations, there are still
important decisions to be made as to where specific tasks should be
solved using multithreading and where they should be solved using other
techniques.
c) In order for you (or Micheal) to justify the "this is
nonsense" response to my "does not buy you anything",
you would have to show that all multi-threaded design
is superior to single-threaded

I think to most people's understanding of English, that's clearly not
the case. For example, if I said it was nonsense to say that cars don't
do any good, I would not have to prove that I should drive a car to my
mailbox in the morning (or even to work, or to the grocery store) to
justify that statement.

Clearly, you have an aversion to multithreading, and I have an aversion
to unnecessarily implementing something as a state machine. My aversion
to use of state machines all over the place is that they throw away the
advantages of high-level languages; a loop no longer looks like a loop,
but rather like a set of state transitions, which you might recognize as
a loop only if you have or bother to draw a state transition diagram.
Apparently, your aversion to threads comes from the potential for
deadlocks and race conditions. I can only say that I prefer one
disadvantage over the other, because at least when reading a
multithreaded application, I can see what's going on.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
J

Joe \Nuke Me Xemu\ Foster

Chris Smith said:
Clearly, you have an aversion to multithreading, and I have an aversion
to unnecessarily implementing something as a state machine. My aversion
to use of state machines all over the place is that they throw away the
advantages of high-level languages; a loop no longer looks like a loop,
but rather like a set of state transitions, which you might recognize as
a loop only if you have or bother to draw a state transition diagram.
Apparently, your aversion to threads comes from the potential for
deadlocks and race conditions. I can only say that I prefer one
disadvantage over the other, because at least when reading a
multithreaded application, I can see what's going on.

Why the false dichotomy? Coroutines have loops that look like loops
without the hassles of free-threading. Of course, if computer science
is assumed to begin and end with Java, then the dichotomy makes sense.
 
P

Programmer Dude

goose said:
<grin> me to shoot at? full-time embedded developer, part-time
troll, is that What I've become ? :)

Nah. "Debate Partner" is the phrase. Trolling is something else
entirely.

very good example. I'll conceded that that example really
is one that could benefit from a multithreaded design.

(of course, a simple fork() system call could possibly
achieve the same result without using threads, but relying
on the OS to schedule your different tasks)

Absolutely. My thought is that the threaded solution probably
is easier to understand and maintain.

In my career, I've only once *needed* multiple threads for
my solution to a problem...

I also have "needed" them only once. And there were surly other
designs available. Threads just seemed to make sense and be the
easiest and most obvious.

App was a "controller" that launched and monitored other apps.
It needed to be able to kill the launched app if it ran too long
(was a machining process with some potential for various hardware
or software lockups).

Easiest design was to spawn a thread to launch the app and wait
for it to finish. When it did, the thread wrote to a shared
status value (writable to the thread, read-only elsewhere) and
terminated. The main process would periodically check that
status value. If it didn't show completion in a specified time,
it set about killing and restarting the app.

Like you, if I had had fork() available, I'd have likely used it,
although that would have meant implementing IPC of some sort. The
nice thing was the thread just naturally shared data.
 
G

goose

Programmer Dude said:
Nah. "Debate Partner" is the phrase. Trolling is something else
entirely.


Absolutely. My thought is that the threaded solution probably
is easier to understand and maintain.

I suspect that it depends on your perspective as much
as the problem on hand. Elsethread, someone said something
about "... if computer science starts and ends with java ..."

The few times when I've had to work *with* (as opposed to
against :) java developers, I've found that the first
/design/ decision being taken is to use threads. This is
possibly because from the perspective of a java-only or
java-mainly developer, its a foregone conclusion if you are
going to use java: threads are inevitable so one may as well
throw them into the design anyway.

My *major* gripe is that, in RealLife(tm) we programmer-types
do 90% maintenance, and 10% new development. Schools and
universities teach *only* how to write something from scratch.

Ok, Ok, there are the few "problems" along the lines of
"there is a bug in the following 30 lines of code, fix it", or
"what does the following code snippet do?". IMHO, this is
terribly unproductive, as very few development shops will
actually tell a programmer, "there is a bug in the next
30 lines of code". The programmer has to figure it out
on their own, *and* figure out /which/ 30 lines out of
a possible thousand.

Throw threads into this can of worms. Now the programmer
has to /also/ understand that some things are happening
/concurrently/, and that the bug they are hunting may
be one of those elusive creatures that *cant* happen
in a single-threaded application

(a show of hands, for all those who have found a race condition
in someone elses code after only a few weeks, I know I have:).

IM_Even_More_HO, the teaching of computer science should be
just that: computer science. The current crop of new grads
that I sometimes have the misfortune to work with leaves
me almost weeping ... "a protocol stack? sure, lets do it
with Objects", "no need to draw a state-machine on paper,
we'll just create two threads to rx and tx".

And we wonder why software is so maintenance-intensive.

I sometimes think that teachers should be emphasising, at
the start of every lecture, "use the right tool for the right
job"; instead we get grads (here in SA, at any rate) whose
course curriculum /has/ included prolog(sp?), and C++, and
delphi, but who will tackle anything thrown their way with
java ("because thats what the industry uses most").
I also have "needed" them only once. And there were surly other
^^^^^
They swear and curse at you, do they :) ?
designs available. Threads just seemed to make sense and be the
easiest and most obvious.

yup. once again, it depends on the environment. if it seems to
be the "best fit", then it probably is.

(<sidenote> this is kinda like malloc() strategies. there's
best-fit and first-fit. I try to go the best-fit route
always, although the impression that I get from many programmers
is that they go the "first-fit" route. the first solution that
they think of is the one they would go with).
App was a "controller" that launched and monitored other apps.
It needed to be able to kill the launched app if it ran too long
(was a machining process with some potential for various hardware
or software lockups).

sounds like a shell of some type.
Easiest design was to spawn a thread to launch the app and wait
for it to finish. When it did, the thread wrote to a shared
status value (writable to the thread, read-only elsewhere) and
terminated. The main process would periodically check that
status value. If it didn't show completion in a specified time,
it set about killing and restarting the app.

aha, a watchdog timer.
Like you, if I had had fork() available, I'd have likely used it,
although that would have meant implementing IPC of some sort. The
nice thing was the thread just naturally shared data.

of course, if you had fork(), you would've been on a unix
machine, in which case you would have had mkfifo, and then simply
treated each communication as reading/writing files :)

goose,
ho ho ho
 
T

Tim Ward

goose said:
(<sidenote> this is kinda like malloc() strategies. there's
best-fit and first-fit. I try to go the best-fit route
always, although the impression that I get from many programmers
is that they go the "first-fit" route. the first solution that
they think of is the one they would go with).

Well, first fit *is* better, innit, at least in its cyclic first fit
variant.

Applied to young graduates, this means that they should use their favourite
languages cyclicly; for each project pick the language whose turn it is
next.
 
G

goose

Chris Smith said:
If that were what you'd said, I'd fully agree.

it wasn't what I said, it was what I possibly *should* *have*
said.
It is correct that Java's APIs and language are designed around the
decision that threads are fundamental, so you're right in that respect.
On the other hand, outside of a GUI application, it's entirely possible
to write single-threaded Java applications today, even if they do I/O.

true, I concede that to you.
The fact that it wasn't possible prior to the release of 1.4 several

several ?
years ago is not very relevant these days.

why not ? iirc, select() was still new to most java developers
2 years ago. java has been available for +- 10 years now, no ?
for the last two years its had a select() type method. it follows
then that the larger volume of code written in java is aimed
at pre-1.4.

do you not agree ?

if you *dont* agree, you are willing to state (and justify)
that more code for java has been written in the last two years
than in the eight prior to that ?

if you *do* agree, then how is pre-1.4 "not very relevant" ?
its only irrelevant for start-from-scratch projects, which are
few and far between.
The requirement for use of threads in a GUI environment mostly comes
from Java's lacking a way to "poll" for events and process them from
within a programmatic loop elsewhere in code. That polling method, so
well-known in VB, is clearly a broken idea in the first place.

do you really think so ? it is not at all clear to me how the
"polling" method is broken. select() (and, funnily enough, poll())
have not been replaced by java equivalents in systems programming,
yet it was seen fit to *add* a method to poll to java.

if its so clearly broken, it would not have been added.
I would
not want to see a GUI application written as a single thread (though
such applications get written all the time in Microsoft VB environments,
and they generally prove how destructive the idea really is).

but *I* used to write gui apps in single-threads. easily maintained,
robust and *clear* applications. I've tried the threaded approach
for gui, and thats "clearly a broken idea" (you justify yours,
and I'll justify mine :).
In the end, though, I don't personally think this question of
multithreading being "required" in Java is relevant, anyway.

no, java is not very relevant to my original argument. in fact,
it was totally irrelevant, as I was talking about computer science,
not java.
After all,
even if multithreading is forced in a few situations, there are still
important decisions to be made as to where specific tasks should be
solved using multithreading and where they should be solved using other
techniques.


I think to most people's understanding of English, that's clearly not
the case. For example,

ok, lets make this example more concrete, no ?
if I said it was nonsense to say that cars don't
do any good,

lets pretend that I did say "cars dont actually buy you
anything [as opposed to some other method of travel]".

you respond with "nonsense". the implication here is that
cars /do/ buy you something [as opposed to some other method
of travel].

I then respond with "these here are the examples where using
a car instead of [some other method of travel] /does/ /not/
buy you anything".

its now your turn to prove my examples logically false, or
to show me that my examples are in the minority (i.e.
"cars buy you more than [other method of travel] in 95%
of cases") or perhaps to show me examples where using a car
over [some other method of travel] is better, etc ad nauseum.

I would not have to prove that I should drive a car to my
mailbox in the morning (or even to work, or to the grocery store) to
justify that statement.

Clearly, you have an aversion to multithreading,

nope, I have an aversion to maintenance-unfriendly code.
I also have an aversion to choosing a more complex solution
over a simple one purely because the problem is already in
a domain chock-full of complex problems.

ever heard of occams razor ?
and I have an aversion
to unnecessarily implementing something as a state machine.

state-machines are nice. you *know* where you are with them.
state-machines are powerfull; for the reader *and* the writer.
going through unfamiliar code which was designed and implemented
as a state-machine results in a few powerfull state-diagrams.

state-machines are as close to self-documenting code as
one can get.
My aversion
to use of state machines all over the place is that they throw away the
advantages of high-level languages; a loop no longer looks like a loop,

trivial loops will always look like trivial loops. complex loops which
are implemented in some haphazard way (at worst) would be better off
as a state-diagram, which terminates properly, not as a loop
which might have any number of "break" or "continue" statements
in them.
but rather like a set of state transitions, which you might recognize as
a loop only if you have or bother to draw a state transition diagram.

nope. you recognise the design pattern, and you dutifully draw
your state-diagram (if you dont have it already). with a
multiple-threaded application, you cant draw *any* diagram that
will accurately reflect the state of the machine at any given
point in time.
Apparently, your aversion to threads comes from the potential for
deadlocks and race conditions.

nope. those are just the results. my "aversion" (not really) comes
from the almost inconsistent state of the machine when there is
more than a single path of execution. A state-machine enables me
to write code which is deterministic down to a single clock cycle
(on some processors).
I can only say that I prefer one
disadvantage over the other, because at least when reading a
multithreaded application, I can see what's going on.

You can see whats going on? please enlighten me: how can you
tell at any given moment exactly *what* is happening? you just
"know" ?

multiple-threads lose out in a big way when the constraints are
1. real-time reactions.
2. consistency in the state the processor is in.
3. documenting the code *from* the code.

an example (say, pseudocode) from you at this point will help.

a simple state-machine of the type:

state = start_state;
while (state!=end_state) {
switch (state) {
case state1: /* do state1, set next state depending */
case state2: /* do state2, set next state depending */
case state3: /* do state3, set next state depending */
case state4: /* do state4, set next state depending */
case state5: /* do state5, set next state depending */
case state6: /* do state6, set next state depending */
}
}

is all on one page/screen; can be used to very quickly draw the
state-diagram to figure out what the original programmer had
in mind; can be used to "count" instructions to know exactly
*how* *long* the machine will execute for, and, if designed
as a proper state-machine (no black-holes, pumping lemmas, etc)
can be used to *gaurantee* that the machine finishes.

you would have to do a lot of work with threads to get all that
above.

cheers
goose,
tis the C-zin to be java-ly ;-)
 
C

Chris Smith

I'm going to try to shorten this again to the core issues to avoid an
ever-growing thread that I have no time to answer. Let me know if I
leave out something that you think is important.
trivial loops will always look like trivial loops. complex loops which
are implemented in some haphazard way (at worst) would be better off
as a state-diagram, which terminates properly, not as a loop
which might have any number of "break" or "continue" statements
in them.

Do you really mean that high-level languages with looping constructs are
a mistake? 'while' considered harmful? Or, in any case, it sounds like
you're saying that at worst a state diagram of a loop is just as good as
the loop itself. I'm afraid you're going to have to make a very good
case for that one. Decades of empirical evidence demonstrate that
programmers prefer to work with normal loops and conditional statements.
nope. you recognise the design pattern, and you dutifully draw
your state-diagram (if you dont have it already).

And then I've spent five minutes trying to understand a piece of code,
only to find it doesn't do what I was expecting anyway! Wouldn't it be
easier if I knew this at a glance from the code itself?
with a
multiple-threaded application, you cant draw *any* diagram that
will accurately reflect the state of the machine at any given
point in time.

Sure, but you can find out what you really need to know. That's the
point: you don't need to see the whole state of an application at once,
and threads give you the tools you need to separate concerns based on
process distinctions, without chaining yourself to a sequential form. I
just have to ensure that shared state is modified atomically to avoid
race conditions (which, incidentally, I also have to do when deciding
when it's appropriate to interrupt one task and resume another under
*any* approach to such a problem).
multiple-threads lose out in a big way when the constraints are
1. real-time reactions.
2. consistency in the state the processor is in.
3. documenting the code *from* the code.

That's odd, because 1 and 3 seem to me exactly like *clear* advantages
of separating unrelated processing into multiple threads instead of
multiplexing state machines on a single thread. I don't even understand
what you mean by item 2.
a simple state-machine of the type:

state = start_state;
while (state!=end_state) {
switch (state) {
case state1: /* do state1, set next state depending */
case state2: /* do state2, set next state depending */
case state3: /* do state3, set next state depending */
case state4: /* do state4, set next state depending */
case state5: /* do state5, set next state depending */
case state6: /* do state6, set next state depending */
}
}

is all on one page/screen;

Errr... well, that's because it doesn't actually *do* anything; you
haven't written any functional code, because all the functional bits
(that is, basically the whole application) go in the place of those
short comments. Besides that, there are only six states there. Try
implementing an actual application that way, even a trivial one, and let
me know if it fits on one page.

On the other hand, I can write some trivial procedural applications
using loops that fit on one page.

And then, to get back to the original problem, show me the code for
putting together multiple state machines that can interrupt each other,
which use some shared data; and show me your strategy for arranging
exclusive access to that shared data, especially when some state
machines sometimes have to wait for data to be made available by other
state machines or from unpredictable external sources like keyboards.
When you've actually taken difficult tasks that cause the now-famous
problems in multithreading and solved them with state machines, then you
can tell me about how the state machine solution is always better than
threads on a uniprocessor.

Oh yeah, then you can go about explaining how you plan to use third-
party libraries that are not aware of your radical plan for handling
concurrent tasks. What if one of them spends too much time doing some
calculation and doesn't return to your control routine so as to let
another more important task run.
can be used to very quickly draw the
state-diagram to figure out what the original programmer had
in mind;

Which, it seems obvious, is only necessary because it's *not*
immediately clear from the code what the programmer had in mind. A
state diagram is no easier to understand than high-level code in most
languages, if that high-level code is written naturally using block-
style flow control.
can be used to "count" instructions to know exactly
*how* *long* the machine will execute for,

Not bloody likely. Are you still writing code using non-optimizing
compilers for 6052 processors? Modern environments include multiple
levels of data caches, very complex pipelining, and smart optimizing
compilers that reorder and rearrange most operations anyway. Simply
put, except in hard real-time environments where you disable most all
features of modern computing environments, benchmarking is the way to
measure performance.
and, if designed
as a proper state-machine (no black-holes, pumping lemmas, etc)
can be used to *gaurantee* that the machine finishes.

Is this a problem in your code? Most people have no problem writing
for/while loops that finish either. Threads don't make that appreciably
harder.

Basically, I think you're taking some problems that arise from very
complex applications written using threads, and then pointing out that
it's easier to write very simple state machine apps than to solve those
hard problems. That's no surprise; we all know it's easier to solve
simple problems than difficult ones. So what?

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
S

Sudsy

Chris Smith wrote:
Do you really mean that high-level languages with looping constructs are
a mistake? 'while' considered harmful? Or, in any case, it sounds like
you're saying that at worst a state diagram of a loop is just as good as
the loop itself. I'm afraid you're going to have to make a very good
case for that one. Decades of empirical evidence demonstrate that
programmers prefer to work with normal loops and conditional statements.
Which, it seems obvious, is only necessary because it's *not*
immediately clear from the code what the programmer had in mind. A
state diagram is no easier to understand than high-level code in most
languages, if that high-level code is written naturally using block-
style flow control.

Let's see if I've got my Nomex(tm) suit on...yep...good!

I question the validity of the statement about "empirical evidence that
programmers prefer" (insert sacred cow here). It's been my experience
that programmers generally prefer to use what they already know instead
of learning something new.
And I strongly disagree with your statement in the second snippet. I
find a state diagram to be far easier to read than high-level block
code. They say that a picture is worth a thousand words and it's a lot
easier IMHO to comprehend the transitions in a state diagram than to
try to deduce them from block code, no matter how high-level.
There are a lot of different tools and approaches out there. Trying to
coerce a problem into a particular domain simply because of familiarity
with a certain toolset will often produce less-than-optimum results. My
mantra is "always use the right tool for the job", even if it happens
to be Assembler H Extended! ;-)
As always, YMMV.
 
C

Chris Smith

Sudsy said:
I question the validity of the statement about "empirical evidence that
programmers prefer" (insert sacred cow here). It's been my experience
that programmers generally prefer to use what they already know instead
of learning something new.

I'd be inclined to agree in the general case, really... except that
we're talking about loop constructs, for goodness sake. If you want to
argue that everyone from the fair lady of Lovelace onward has been wrong
about programming languages, I'm afraid you're going to have to come up
with something substantial to say about it. Sure, presumption from
experience only goes so far; but it goes much farther when experience is
so universal as the dominating trend in programming language design over
the past 10 to 15 decades (approximately... forgive me if I don't have
exact dates for Ms. Ada's work on the Difference Engine).
There are a lot of different tools and approaches out there. Trying to
coerce a problem into a particular domain simply because of familiarity
with a certain toolset will often produce less-than-optimum results. My
mantra is "always use the right tool for the job", even if it happens
to be Assembler H Extended! ;-)

The problem with the phrase "use the right tool for the job" is that
it's circular, and therefore meaningless. Certainly, no one's going to
argue that, in fact, we ought to prefer the wrong tool for the job! As
such, it gets somewhat tiresome to hear people always repeating it, as
if it had some meaning. You see, that's the problem with the right tool
for the job: everyone knows we ought to use it, but no one quite knows
what it is. In my own humble opinion, there are a few things to
remember about the right tool for the job, which are often contrary to
someone's intention when they use that insidious phrase:

1. When it's rather non-trivial to learn how to use a new tool
effectively, the right tool for the job is often the one most broadly
useful, even if a more obscure tool might theoretically be better for a
particular task.

2. When the job will be long, and will likely gain and lose workers over
time, the right tool is one that a lot of people know how to use at some
minimum level of productivity; even if another tool would be more
productive when operated by experts.

3. Regardless of the implications of the phrase, there are some tools
that are NEVER the right tool for the job. For example, no software
should ever be written in Intercal. Ever. End of story. (No, of
course state machines don't fall into that category... just being more
general.)

So, I hope you'll forgive me for saying that when the familiar "right
tool for the job" phrase gets used to try to stop programmers from
writing loops, I'm a bit suspicious about the level of objectivity that
was applied in choosing the right tool.

(I also don't mean to imply that your having such a mantra is without
meaning. For example, if you mean that you see choosing the right tool
as primary in comparison to other parts of your job -- such as
perfecting the architecture, matching developer skill sets to tasks, etc
-- that's an understandable value set, though I may not agree with it.
I just object when the phrase is used as if there were others out there
trying *not* to choose the right tool.)


And the other part of the discussion:
And I strongly disagree with your statement in the second snippet. I
find a state diagram to be far easier to read than high-level block
code. They say that a picture is worth a thousand words and it's a lot
easier IMHO to comprehend the transitions in a state diagram than to
try to deduce them from block code, no matter how high-level.

I'm entirely willing to accept that this is, perhaps, just my bias. I
don't like diagrams... never have, and possibly never will. That's
because they seem pointless to me in comparison to other representations
of the same information, and they rarely contain all the information I
want to see. Chances are, I'm just not a visual thinker in that sense.
On the other hand, I am very picky about stylistic concerns in code that
make it more obvious at a glance, because that's how I understand what's
going on more easily.

Regardless, there are many, many ways to put together diagrammatic
representations of control flow without writing the code as a state
machine. The point is that when the code is written as a state machine,
a diagram is the *only* way to see at a glance what the code is doing.
I realize that there's a fad going around of pretending that code is
unreadable (mostly propogated by companies with a vested interest in
UML-based design tools), but it's not true. We're going to lose a lot
of productivity as a software industry if we forget that code is
supposed to be readable by human beings as well as machines, *without* a
design reverse-engineering step, and without a decoding step to produce
a diagram.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,128
Latest member
ElwoodPhil
Top