2000 to: 2021 do: [ :year | date := Date year: year month: 12 day: 5. date weekday == #Friday ifTrue: [Transcript print: year; cr; flush.] ]Answer:
2003 2008 2014
An occasionally updated blog, mostly related to programming. (Views are my own, not my employer's.)
2000 to: 2021 do: [ :year | date := Date year: year month: 12 day: 5. date weekday == #Friday ifTrue: [Transcript print: year; cr; flush.] ]Answer:
2003 2008 2014
#lang racket (require mrlib/gif) (require racket/draw) (define (random-lines-bitmap width height line-count) (let* ([target (make-bitmap width height)] [dc (new bitmap-dc% [bitmap target])]) (begin (send dc draw-rectangle 0 0 ; Top-left at (0, 10), 10 pixels down from top-left (- width 1) (- height 1)) (for ([i line-count]) (send dc draw-line (random width) (random height) (random width) (random height))) target))) (define (write-random-lines-gif width height line-count frame-count filename) (write-animated-gif (for/list ([i frame-count]) (random-lines-bitmap width height line-count)) 10 filename #:loop? true)) (write-random-lines-gif 300 200 50 10 "random-lines.gif")
"https://evincarofautumn.blogspot.com/2012/02/why-concatenative-programming-matters.html" >url http-get* length ... 261104(This seems to work. Am I leaving extra stuff on the stack?)
sudo port install clojure +rlwrap sudo port install openjdk11
clj user=> (+ 1 1) 2Woohoo!
Brooks uses the metaphor of the tower of Babel to again emphasize the importance of but difficulties with communication. Several times he (again) brings up problems with potential superlinear complexity owing to to the number of pairs or other groupings of workers.
"How, then, shall teams communicate with one another? In as many ways as possible: Informally... Meetings... Workbook..."
He goes into some detail talking about the workbook and processing surrounding it. It seems that online documentation has solved a lot of his problems though introducing new ones. He talks about the introduction of microfiche to avoid printing out an unwieldy number of pages, but notes the lack of ability to add notes as an important limitation. We have that problem too with online docs -- no margins to write in as an individual reader. Also, support for showing diffs in documentation is pretty uneven.
"If there are n workers on a project, there are (n^2 - n)/2 interfaces across which there may be communication, and there are potentially almost 2^n teams within which coordination must occur. The purpose of organization is to reduce the amount of communication and coordination necessary... The means by which communication is obviated are division of labor and specialization of function."
A tree structure arises because no one should have two bosses. Brooks also notes even if the reporting change forms a tree, plenty of communication outside this is necessary, forming a network.
Necessaries for any subtree:What Brooks calls "producer" sounds very much just like "manager" or "technical lead manager" to me while "technical director" seems to map very closely to what I think I know of as "tech lead". (In the group I'm reading this with, we had noted some of the roles he described seemed a bit unfamiliar, but here even if the names are different, the roles seem pretty close to what we have today.)
He talks about three possible arrangements between producer and director: same person, director reports to producer, or producer reports to director. He illustrates the 3rd arrangement, which I don't believe I've seen in real life, with a quote from Heinlein's "The Moon is a Harsh Mistress" where the top engineer is happy to be freed from management work.
x <- 1:32 image(x, x, outer(x, x, FUN=function(x, y) (bitwXor(x, y) %% 9) != 0), col=c("white", "black")) dev.copy(png, "~/x_xor_y_mod_9.png") dev.off()Looking forward to creating a GIF using the gifski package, which I learned about from gganimate, which I'm also looking forward to exploring.
import os.path from contrib import gif from org.das2.graph import DasColorBar def xor_mod_plot(n=256, modulus=9): x = outerProduct(linspace(0, n - 1, n), ones(n)) plot(gt(bitwiseXor(x, transpose(x)) % modulus, zeros(n, n)), renderType='nnSpectrogram>rebin=noInterpolate') dom.plots[0].setColortable(DasColorBar.Type.GRAYSCALE) gif.plot_to_gif(xor_mod_plot, os.path.expanduser('~/autoplot/xor_mod_zoom.gif'), keyword_params=[dict(n=n) for n in range(4, 513)], delay_tenths_sec=5)The only change required for the GIF-writing code was the call to writeToBufferedImage(), which required an explicit import when used within the library:
from org import autoplot ... images.append(autoplot.ScriptContext.writeToBufferedImage())
import os.path import jarray from org.das2.graph import DasColorBar from java import io from java.awt import image as awtimage from javax import imageio import javax.imageio.metadata import javax.imageio.stream ARGB = imageio.ImageTypeSpecifier.createFromBufferedImageType(awtimage.BufferedImage.TYPE_INT_ARGB) COMMON_GIF_ATTRIBUTES = { 'disposalMethod': 'none', 'userInputFlag': 'FALSE', 'transparentColorFlag': 'FALSE', 'transparentColorIndex': '0', } LOOP_NODE_ATTRIBUTES = { 'applicationID': 'NETSCAPE', 'authenticationCode': '2.0', } def set_node_attr(node, attributes_dict): for key, value in attributes_dict.items(): node.setAttribute(key, value) def write_gif(images, path, delay_tenths_sec=5, loop=True): if not images: return gif_writer = imageio.ImageIO.getImageWritersBySuffix('gif').next() write_param = gif_writer.getDefaultWriteParam() metadata = gif_writer.getDefaultImageMetadata(ARGB, write_param) metadata_format = metadata.getNativeMetadataFormatName() print metadata_format root = metadata.getAsTree(metadata_format) graphics_control_extension_node = imageio.metadata.IIOMetadataNode('GraphicControlExtension') root.appendChild(graphics_control_extension_node) graphics_control_extension_node.setAttribute('delayTime', '%d' % delay_tenths_sec) set_node_attr(graphics_control_extension_node, COMMON_GIF_ATTRIBUTES) if loop: app_extensions_node = imageio.metadata.IIOMetadataNode('ApplicationExtensions') root.appendChild(app_extensions_node) app_extension_node = imageio.metadata.IIOMetadataNode('ApplicationExtension') app_extensions_node.appendChild(app_extension_node) set_node_attr(app_extension_node, LOOP_NODE_ATTRIBUTES) app_extension_node.setUserObject(jarray.array([1, 0, 0], 'b')) metadata.setFromTree(metadata_format, root) out = imageio.stream.FileImageOutputStream(io.File(path)) gif_writer.setOutput(out) gif_writer.prepareWriteSequence(None) for image in images: gif_writer.writeToSequence(imageio.IIOImage(image, None, metadata), write_param) gif_writer.endWriteSequence() out.close() def plot_to_gif(plot_func, path, keyword_params=[], delay_tenths_sec=10, loop=True): images = [] for params in keyword_params: plot_func(**params) images.append(writeToBufferedImage()) write_gif(images, path, delay_tenths_sec=delay_tenths_sec, loop=loop) def xor_mod_plot(n=256, modulus=9): x = outerProduct(linspace(0, n - 1, n), ones(n)) plot(gt(bitwiseXor(x, transpose(x)) % modulus, zeros(n, n)), renderType='nnSpectrogram>rebin=noInterpolate') dom.plots[0].setColortable(DasColorBar.Type.GRAYSCALE) annotation(0, text='m = %d' % modulus, borderType='Rounded_Rectangle') plot_to_gif(xor_mod_plot, os.path.expanduser('~/autoplot/xor_mod.gif'), keyword_params=[dict(modulus=m) for m in range(2, 255)], delay_tenths_sec=50)
x = outerProduct(linspace(0, 255, 256), ones(256)) plot(gt(bitwiseXor(x, transpose(x)) % 9, zeros(256, 256)))I'm pretty happy with how it turned out. I don't have time now to dig into what's going on with the image much now, but zooming in on one corner may help:
def xorModPlot(n=256, modulus=9): x = outerProduct(linspace(0, n - 1, n), ones(n)) plot(gt(bitwiseXor(x, transpose(x)) % modulus, zeros(n, n))) xorModPlot(n=32)The 45 degree diagonal line makes sense since any integer XOR-ed with itself = 0. I was going to say that this raises another question, how much is accounted for the XOR operation alone. But, naturally, for any x != y, they differ in at least one bit and so x ^ y != 0 in that case. Notes:
Trying to restate the main points of Chapter 2 of "The Mythical Man-Month" mostly in my own words:
The majority of software projects fail due to lack of calendar time.
Reasons:
Optimism
"All programmers are optimists". The flexibility of programming may contribute to this: "The programmer builds from pure thought-stuff: concepts and very flexible representations thereof." Having the power to do anything makes you think that you can do anything easily. However, then problems with our ideas creep in as bugs, making that optimism unrealistic.
(This great flexibility implies a big search space, and a need -- or at least possibliity -- for more creativity. Is it right that programmers are more prone to over optimism, accounting for the novelty of the problem being solved?)
In a big project with many subtasks, the probability that everything will go well is teeny. (Brooks says, "The probability that each will go well...", but I guess he meant, "The probability that all will go well...")
The SWE-Month
While cost necessarily increases with both the time taken and the number of workers, progress does not. "Hence the man-month as a unit for measuring the size of a job is a dangerous and deceptive myth."
The two are interchangeable only if work can be divided amongst workers without requiring communication between workers. "[I]t is not even approximately true for systems programming."
If a task is sequential by nature, it cannot be partitioned and so clearly cannot be sped up by adding more workers. Debugging can make tasks sequential. (Huh? Fixing one bug reveals another??)
For tasks that can be partitioned but require communication, the cost of communication must be accounted for.
Two types of communication costs:
The extra cost from communication may be so high that it actually ends up slowing the project down.
Systems test
(Most impacted by sequential constraints because it needs to happen after rest of system is complete? Can test driven development help here?)
Rule of thumb for planning software schedule:
Although it's uncommon to budget half of project time for testing, in reality, the author observed testing to actually take this amount of time for most projects. Under budgeting for testing can be particularly disastrous because the bad news comes close to the promised delivery date, when the cost per day is at maximum and failures are most visible to customers.
Giving into customer/management pressure to overpromise: gutless estimating
Lacking confidence in their estimates, managers find it hard to push back on customer/management desire for unreasonably optimistic planned delivery dates. The solution is to improve those estimation methods but also to recognize that even a rough estimate is better than wishful thinking and so to push back.
Regenerative Schedule Disaster
Brooks's Law: Adding manpower to a late software project makes it later.