Let me start by saying that I am no accountant or financial expert so there is no reason whatsoever to think that anything I say here makes any sense. On the other hand it makes complete sense to me and I can't see how any reasonable thinking person could disagree with what I say. If you know better, please, pretty please take the time to educate me.
I have seen a whole bunch of articles and blogs lately that claim that Mark to Market (M2M) accounting is to blame, or partly to blame, for the bubble that caused our current financial crisis. Some of these call for a suspension of M2M, others call for a ban of M2M, and still others think that M2M is critical and should be left alone.
OK, so what the heck is M2M? Also sometimes called fair market accounting, it is the practice of putting assets on the books at their market value. So if I own 100 shares of company X and those shares are trading at $100, then I would put the value on the books as $10,000. This makes total sense to me. In fact the only thing that doesn't make sense to me is the fact that this is relatively new. M2M accounting rules were only put in place in response to the Enron fiasco. It is crystal clear to me that if I am an investor, I want to see the best possible approximation of the value of the company I am investing in and M2M accounting is the best way to show that real value.
Or at least it is when the assets are liquid. But what happens when you think the market value of an asset is $10,000, but there is no way in Hell that you could sell it to anyone at the moment? Well, that's a problem. It clearly isn't really worth $10,000 in that case. You could only estimate the value by estimating when you could sell for $10,000 and subtracting the associated opportunity costs.
Or what happens if Mr. Market is temporarily insane and wants to pay $10,000 for something that is only really (intrinsically) worth $1000? This is the heart of the argument that M2M caused the bubble. Irrational exuberance caused book values to be hugely inflated, leading to big loans that couldn't possibly be paid back and so forth.
OK, so you need to have M2M accounting in order to tell investors what the real value is, but if you have M2M accounting it can lead to different problems in illiquid or irrational markets. What can be done?
In my opinion, we should just require full disclosure. We should stop letting corporations hide things in spreadsheets that assume that there is a single rational value for all assets. There is not and never will be a single accounting method that is even a vague representation of the truth.
I would like to see assets reported as M2M and cost (price paid) and an estimate of intrinsic value (when possible, perhaps a liquidation value or an arbitrage value), along with estimates of liquidity. If I am a shareholder, then I am an owner of your company and I insist on knowing how you run my business.
Would this prevent bubbles? Of course not. People are intrinsically irrational. But at least you could look at what they did and laugh at them for being stupid.
David
Tuesday, October 7, 2008
Thursday, September 18, 2008
Pretty Sourdough
I am totally jealous that John got brotforms, but you can make pretty loaves freehand too. :-P
My standard white sourdough.
David
My standard white sourdough.
David
Saturday, September 13, 2008
Thoughts on Genius
I just installed iTunes 8 with the new Genius music recommendation/playlist feature. I have played around with similar functionality for years in the form of Pandora and MusicBrainz. These tools are how I find new music anymore (combined with iTunes own recommendation system and Amazon's recommendations). I have not listened to the radio in a few years at least.
Genius is pretty cool when it works. It instantly generates a very mood appropriate playlist from a selected song, which is nice. The Genius side bar shows a whole bunch of recommendations too - this function blows away the old school iTunes recommendation system since it allows you to look for specific kinds of music.
But it completely fails on obscure tracks and obscure genres. Even on obscure tracks and genres purchased from the iTunes store. It is useless for classical music, usless for traditional irish music, usless for some classically influenced electronica (where useless is defined as not recognizing a large enough fraction of similar songs to build interesting playlists, not as the complete inability to recognize anything at all). It doesn't work for music videos at all, unfortunately, either (come on Apple - that should be easy to solve for videos purchased in the iTunes store).
Still it works for some surprisingly obscure stuff and it is wicked fast. I'll definitely be using it.
But if you find yourself getting the message, "Genius is unavailable for the song..." frequently, do yourself a favor and install MusicBrainz.
David
P.S. I have also discovered that it works differently for music purchased from iTunes vs. other music. Even if the tracks are identical otherwise (different formats, but the same sound signature).
Genius is pretty cool when it works. It instantly generates a very mood appropriate playlist from a selected song, which is nice. The Genius side bar shows a whole bunch of recommendations too - this function blows away the old school iTunes recommendation system since it allows you to look for specific kinds of music.
But it completely fails on obscure tracks and obscure genres. Even on obscure tracks and genres purchased from the iTunes store. It is useless for classical music, usless for traditional irish music, usless for some classically influenced electronica (where useless is defined as not recognizing a large enough fraction of similar songs to build interesting playlists, not as the complete inability to recognize anything at all). It doesn't work for music videos at all, unfortunately, either (come on Apple - that should be easy to solve for videos purchased in the iTunes store).
Still it works for some surprisingly obscure stuff and it is wicked fast. I'll definitely be using it.
But if you find yourself getting the message, "Genius is unavailable for the song..." frequently, do yourself a favor and install MusicBrainz.
David
P.S. I have also discovered that it works differently for music purchased from iTunes vs. other music. Even if the tracks are identical otherwise (different formats, but the same sound signature).
Thursday, September 11, 2008
Programming's Dirtiest Secret
Stevey has up a brilliant rant about developers and touch typing. But touch typing ability (or lack thereof) isn't really the dirtiest secret about programming. Even though I can touch type, I am going to use a lot fewer words than Stevey did. Ready?
David
People are, on average, pretty darn average. Developers are no exception.
In most endeavors average is pretty bad. Software development is no exception.
Telling the difference between an average developer and a great one in an interview is really hard.
David
Developer Best Practices
I have been thinking about best practices at work and I am going to throw some ideas out here to help me think them through and to get feedback if any of you have opinions. This isn't complete or well organized - I am just trying to get the juices flowing.
Recommended reading for best practices:
David
- Do not rely on this or any other document to provide a complete list of best practices. There are too many and some seem too obvious to talk about. You are a professional software developer - learn the craft. Don't stop learning. Aim for 10X.
- There is no absolute "best" way to do anything. Think about what you are trying to accomplish. Be pragmatic.
- Design applications in layers. Create distinct modules or blocks of function. Design the module interfaces first. Design by contract.
- Write unit tests.
- At a minimum write unit tests of the module interfaces.
- Ideally write the tests before the code.
- If you are about to debug something, stop and write a unit test for it first.
- Don't create mindless unit tests. The auto-generated ones your IDE makes for you are only stubs - don't rely on them for coverage.
- Inject your dependencies as a matter of course. This will greatly simplify unit testing. You don't actually need a framework for this - understand the underlying principle instead.
- Keep stuff in source control (SVN, CVS).
- Do frequent check-ins.
- Comment your commits.
- Don't rely on your IDE to do builds. Have a build script instead.
- Have an independent environment where the build script can be run that is not a developers personal space. Ideally do continuous integration here, but at a minimum regularly check that this build environment still works. Use this environment to build releases.
- Settle on a layout style for the team. It doesn't matter which style, it matters more that everyone is consistent. Or just agree to do it differently and people can reformat their code using their IDEs. But make sure everyone is on the same page.
- Optimize code only when you have demonstrated that it performs poorly. Make a regular practice of benchmarking modules. Run the benchmarks with your unit tests so you know when something gets really out of whack.
- Employ regular peer review of some kind. Internal code reviews. Pair programming. Whatever works for your team. This is how bad code gets found and how developers learn to get better.
- Also have occasional external code reviews that involve more than just the immediate team.
- Encourage zero code ownership. Everyone owns all of the code. Anyone can change/fix anything. Any bug is everyone's responsibility.
- Use tools regularly to check for common bugs/problems. If I review your Java code I am going to run findbugs on it - so you should too.
- Minimize local configuration information in multi-tier applications. An ideal java midtier should only need to know one thing - a JNDI datasource from which all other configuration information can be derived. An ideal thick client should get global configuration from the server.
- Always close resources. Take full advantage of try/finally blocks.
- Don't reinvent the wheel. Use the core libraries of your platform. If you are writing in Java and you think you need to write a sort routine, or a string to date routine, or an array copy routine: STOP. Find good adjunct libraries and use them.
- Have a well thought out strategy for handling exceptions and logging. All errors should be logged, preferably once. The log entry should give enough information to lead back to the root cause. It should be time stamped. It should contain a stack trace if applicable. It should have a context appropriate message that can be understood by someone not intimately familiar with the code.
- Do your release cycles faster. I don't care how fast you are doing them now, go faster.
- It is OK to make pragmatic short term compromises in your code, but make sure you go back and fix them very soon. Do not fall into the boiled frog trap.
- Eat your own dog food. If you design a service interface and never actually use it, chances are it will actually be unusable in some way. The same for a user interface.
Recommended reading for best practices:
- The Pragmatic Programmer - if you program at all in any language and you haven't read this book, go read it now.
- Effective Java - if you program in Java, you need to read this.
- Code Complete
David
Thursday, September 4, 2008
What Does Good Software Look Like?
Good software looks and feels like this:

(I drew this - feel free to make fun of my artistic abilities)
And bad software looks and feels a lot more like this:

(image credit)
Far too much of the code that I look at invokes the latter image. Stop it please.
David

(I drew this - feel free to make fun of my artistic abilities)
And bad software looks and feels a lot more like this:
(image credit)
Far too much of the code that I look at invokes the latter image. Stop it please.
David
Tuesday, August 19, 2008
On JavaFX
JavaFX has the potential to be a really cool technology, but it has a little ways to go yet.
At work we are trying to figure out what we want to do in the Rich Internet Application space and I was asked to review JavaFX to ensure that it could perform one really critical niche function - that it can be used with existing libraries to display chemical structures. The simple answer is that it can. I had no trouble at all writing very thin plain Java wrapper classes around ChimePro, Marvin Beans, and JMol so that I could use them in a JavaFX script.
The more complicated answer, though, is that there are still lots of gotchas.
One of the central powers of JavaFX is that it can use any Java library, but that might also be its downfall, especially if it gets widely adopted by mediocre Java programmers. One of the reasons that Applets have gone the way of the Dodo bird is that people had a tendency to bloat the jar downloads to the point that the Applets were slow and finicky and painful to use. The same is certainly possible with JavaFX. Don't do this. Keep the presentation layer as thin and clean as you possibly can.
The allure of a declarative scripting language for rich application development that harnesses all of the power of the Java platform is undeniable and I will continue to play with the technology as it matures. But it isn't quite ready for prime time yet.
David
correction: Where I said Scene I should have said Stage. My memory tricked me. I am referring to javafx.application.Stage.
In answer to a question in the comments, here is an example of how to turn JMol into a JComponent. Note that although you don't see long lines in the blog, when you copy/paste the text you seem to get it all. I'm not sure why and I am open to suggestions for better ways to include code.
At work we are trying to figure out what we want to do in the Rich Internet Application space and I was asked to review JavaFX to ensure that it could perform one really critical niche function - that it can be used with existing libraries to display chemical structures. The simple answer is that it can. I had no trouble at all writing very thin plain Java wrapper classes around ChimePro, Marvin Beans, and JMol so that I could use them in a JavaFX script.
The more complicated answer, though, is that there are still lots of gotchas.
- The API has been in a state of flux, so code examples that you can google up tend to be unusable (ignore anything dated 2007 or that has an import for javafx.ui.*).
- The API is still fluxing, so you can expect lots of changes soon. One critical bit that relates to my Swing component test is that the base display (container) classes are changing. To get the cool "drag from the browser" behavior you need to start with the Application class (or maybe Applet) and add Nodes to the Scene, but to use Swing components you have to use the older containers (that work fine for a JNLP application). And you can't easily subclass Node to fix this yourself because it is an abstract class that has an abstract method that returns an object in the com.sun.* hierarchy - something you probably shouldn't mess with.
- There isn't a lot of good information out there. There is one book. It is a decent book, but it tried to hit a moving target so it isn't perfect. Combine the book with the author's blog and you have one good source of information. The API documentation and related Sun documents is the other good source of information, but it is still far less complete than, say, the Java documentation.
- Netbeans integration is not complete. It is really well done, it just isn't quite finished. The visual constructor/previewer is brilliant, but there isn't support yet for fixing problems (e.g. fixing imports) - you just get a red (!) and you have to figure out why (and the compiler messages aren't really all that informative ("I got confused by...")).
One of the central powers of JavaFX is that it can use any Java library, but that might also be its downfall, especially if it gets widely adopted by mediocre Java programmers. One of the reasons that Applets have gone the way of the Dodo bird is that people had a tendency to bloat the jar downloads to the point that the Applets were slow and finicky and painful to use. The same is certainly possible with JavaFX. Don't do this. Keep the presentation layer as thin and clean as you possibly can.
The allure of a declarative scripting language for rich application development that harnesses all of the power of the Java platform is undeniable and I will continue to play with the technology as it matures. But it isn't quite ready for prime time yet.
David
correction: Where I said Scene I should have said Stage. My memory tricked me. I am referring to javafx.application.Stage.
In answer to a question in the comments, here is an example of how to turn JMol into a JComponent. Note that although you don't see long lines in the blog, when you copy/paste the text you seem to get it all. I'm not sure why and I am open to suggestions for better ways to include code.
package fxstructurerendertest;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import org.jmol.api.*;
import org.jmol.adapter.smarter.*;
public class JMolDisplay extends JComponent implements ActionListener {
private static final long serialVersionUID = -5404266974773735194L;
private JmolViewer viewer;
private JmolAdapter modelAdapter;
private JPopupMenu popup = new JPopupMenu();
private JCheckBoxMenuItem dotsItem = new JCheckBoxMenuItem("Dots");//dots on/dots off
private JCheckBoxMenuItem spaceItem = new JCheckBoxMenuItem("Spacefill");//spacefill on/spacefill off
private JCheckBoxMenuItem ribbonItem = new JCheckBoxMenuItem("Ribbon"); //ribbon on/ribbon off
private JCheckBoxMenuItem colorAminoItem = new JCheckBoxMenuItem("Color Amino");//color amino/color NONE
private JCheckBoxMenuItem colorChainItem = new JCheckBoxMenuItem("Color Chain");//color chain/color NONE
private JCheckBoxMenuItem bondItem = new JCheckBoxMenuItem("Bonds");//wireframe 25/wireframe off - SELECTED
private JCheckBoxMenuItem atomItem = new JCheckBoxMenuItem("Atoms");//cpk 25/cpk 0 - SELECTED
private JMenuItem resetItem = new JMenuItem("Reset");//reset
public JMolDisplay() {
modelAdapter = new SmarterJmolAdapter(null);
this.setPreferredSize(new Dimension(100, 100));
viewer = JmolViewer.allocateViewer(this, modelAdapter);
viewer.setJmolDefaults();
viewer.setColorBackground("BLACK");
this.addMouseListener(new PopupListener());
bondItem.setSelected(true);
popup.add(dotsItem);
popup.add(spaceItem);
popup.add(ribbonItem);
popup.add(colorAminoItem);
popup.add(colorChainItem);
popup.add(bondItem);
popup.add(atomItem);
popup.add(resetItem);
dotsItem.addActionListener(this);
spaceItem.addActionListener(this);
ribbonItem.addActionListener(this);
colorAminoItem.addActionListener(this);
colorChainItem.addActionListener(this);
bondItem.addActionListener(this);
atomItem.addActionListener(this);
resetItem.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
Object c = e.getSource();
if (c == dotsItem) dots();
else if (c == spaceItem) spacefill();
else if (c == ribbonItem) ribbon();
else if (c == colorAminoItem) amino();
else if (c == colorChainItem) chain();
else if (c == bondItem) bond();
else if (c == atomItem) atoms();
else if (c == resetItem) {
if ((e.getModifiers() & ActionEvent.ALT_MASK) != 0) {
ScriptDialog d = new ScriptDialog();
d.pack();
d.setVisible(true);
} else reset();
}
}
private void reset() {
runScript("reset");
}
private void atoms() {
//log.debug("cpk toggle");
if (atomItem.isSelected()) runScript("select all;cpk 100");
else runScript("select all;cpk 0");
}
private void bond() {
//log.debug("bond toggle");
if (bondItem.isSelected()) runScript("select all;wireframe 25");
else runScript("select all;wireframe off");
}
private void chain() {
//log.debug("chain color toggle");
if (colorChainItem.isSelected()) runScript("select all;color chain");
else runScript("select all;color NONE");
}
private void amino() {
//log.debug("amino color toggle");
if (colorAminoItem.isSelected()) runScript("select all;color amino");
else runScript("select all;color NONE");
}
private void ribbon() {
//log.debug("ribbon toggle");
if (ribbonItem.isSelected()) runScript("select all;cartoon on\ncolor cartoons structure");
else runScript("select all;cartoon off");
}
private void spacefill() {
//log.debug("spacefill toggle");
if (spaceItem.isSelected()) runScript("select all;spacefill on");
else runScript("select all;spacefill off");
}
private void dots() {
//log.debug("dots toggle");
if (dotsItem.isSelected()) runScript("select all;dots on");
else runScript("select all;dots off");
}
public JmolViewer getViewer() {
return viewer;
}
class PopupListener extends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
showPopupIfNeeded(e);
}
@Override
public void mouseReleased(MouseEvent e) {
showPopupIfNeeded(e);
}
private void showPopupIfNeeded(MouseEvent e) {
if (e.isPopupTrigger()) {
popup.show(e.getComponent(),
e.getX(), e.getY());
}
}
}
public void runScript(String script) {
viewer.evalString(script);
}
class ScriptDialog extends JDialog implements ActionListener {
JTextArea scriptArea;
ScriptDialog() {
scriptArea = new JTextArea();
scriptArea.setPreferredSize(new Dimension(200,200));
this.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(scriptArea, BorderLayout.CENTER);
JButton runButton = new JButton("Run");
this.getContentPane().add(runButton, BorderLayout.SOUTH);
runButton.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
runScript(scriptArea.getText());
}
}
/**
*
* @param structure
*/
public void setStructure(String structure) {
viewer.openStringInline(structure);
}
/**
*
*/
@Override
public void paint(Graphics g) {
Rectangle rectClip = new Rectangle();
g.getClipBounds(rectClip);
viewer.renderScreenImage(g, this.getSize(), rectClip);
}
}
Subscribe to:
Posts (Atom)
