Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I'm not quite sure what the issue is here. It turns out that the author modeled the domain incorrectly. At least that incorrect model is completely explicit in the code. If it weren't spelled out explicitly, the coupling that the author speaks of would be insidiously spread throughout the code. In order to make the change that the author wants, it's as easy as introducing a new abstract class. In fact, if all the existing code correctly assumes the existence of an Isin, we can create the following set of classes:

abstract class BaseSecurity { public string Description { get; set; } public Exchange Exchange { get; set; } }

then modify Security to derive from BaseSecurity:

abstract class Security : BaseSecurity { public string Isin { get; set; } }

Then you are done, except for two issues: first is that any serialized data needs to be regenerated, and second is that you can't trade BaseSecurities. However, this trading functionality can be written separately without disturbing the existing ecosystem of software. This is what your type hierarchy buys you.

On the other hand, if we insist that this is not correct, and Security should have Isin removed, then we can add a new PhysicalSecurity between Security and the various implementations, and Stock/Bond/Trade can inherit from PhysicalSecurity.

In that case, the problem is that a lot of code was written with the incorrect assumption that an Isin exists in every security. Now we have to take a step back and ask how to fix that code on a case by case basis. No matter what language you use, it's always possible to write bad code with incorrect assumptions, and in that case you must pay the price. Hopefully you would be clear with your client on the delays required.

Now we can ask ourselves how a static language treats the situation differently than a dynamic language. The author seems to think a dynamic language would help, providing only praise in his description of them.

With a static language, we can simply remove Isin from the definition of Option. This will cause a lot of compilation failures. However, every place where there is a compilation failure is a place in the code which had an incorrect assumption. Each of these incorrect assumptions must be considered individually. After all, this represents the model for a trading system, and any bugs would likely result in severe financial consequences.

In a dynamic language, the definition could be changed, but there would not be any inherent mechanism to catch the now-incorrect calls. Instead, we would just get the NullPointerExceptions that the author complains about and which jeopardize the viability of the financial trading system. Perhaps the coders would have written beautiful unit tests that would help, but that could be the case in any static language as well. Of course, it's also possible that the coders would have created trivial unit tests or no tests at all.

In any case, I see this situation as a win for static type systems rather than a loss.



Hey, author here.

Indeed the domain is modelled incorrectly, the problem being that this realisation that this is the case has come late on in the development process. Perhaps in my simplified example that's something you could pick up on before work commenced, but in reality there are many little (and sometimes big) things which you either miss no matter how hard you try, or change later on.

The problem with your suggestions as to fixing the hierarchy is that, yes this is something you ought to do and it resolves the problem, but it takes time and is in essence yak shaving, or at least feels that way - are you really working towards making your software better, or are you just pandering to the abstraction you've created?

In any case, this is one of the 2 options I suggest to resolve the situation, and definitely the correct one (I cover the idea of separating out ISIN and non-ISIN instruments as e.g. physical/derivative), however it takes time and the problem is it is so often the case that time pressures result in you hacking around the problem, making the hierarchy not only incorrect, but actively misleading.

I didn't mean to suggest dynamic languages were a silver bullet here, nor did I mean to put particular emphasis on them.

No matter what you will have to refactor, but the question is whether a rigid hierarchy makes that more or less difficult, and whether that rigidity tempts you into hacks which make this structure misleading.

I think the problem with putting any particular example in the article is that it will inevitably be inadequate for its purpose. The problem really bites when you've experienced a large code base have some small incongruity that doesn't quite fit the model, but I don't think I could clearly and simply express that in code.


There are always time trade-offs. When the overall software design becomes tightly coupled with the type system you simplify the code. You could abstract the way you handle messages, but at some point you need to get the ISDN for some security and no amount of abstraction let's you avoid that.

Now, as you say doing it the right way can take significant amounts of time. But so do the hacks it's just a question of when to spend the time. IMO, front loading the costs is much better because you get a clear understanding of what adding each feature actually costs.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: