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

    We are faced with the dilemma - a lot of the code is now reliant on Isin, and NullReferenceExceptions are getting thrown all over the place because the field isn’t getting populated
Sounds like it's catching bugs. You get to fix all the Isin places in a single unit test pass. Or you change the types and it's all fixed by getting it to compile.

The examples provided by the author are absolutely horrible code. A type hierarchy can be more than two deep. How about adding another base type for securities with ISINs?

Moreover, if you ever see code like security is Option or a switch based on the name of the type it is a great sign of poorly architected code.

The solutions provided aren't really solutions at all. How would functional programming solve the problem? If anything a lot of functional languages are even more rigidly typed than C#.



(Author here) I agree that the code is horrible :-) that's kind of the point - if you choose to hack up your code, then you end up with horrors like if(foo is Bar) { ... } else { ... }.

The type declarations are, I'd argue, not horrible at the outset, but once you introduce the new requirements then it becomes incorrect. I even suggest possible solutions including adding depth to the hierarchy - the point is doing that means yak shaving, not doing it results in a definitely horrible object-orientated design because it no longer fits the problem.

You can argue that you should have a better model from the outset given the coarse change which comes into play, which is potentially where my example starts to break down (I think it would be hard to find an example that would not break down in some way here, given the need to compress reality into a blog post), so take it as read that in reality the changes are often a lot more subtle than the example I give.

The point is that you're having to make far-reaching, rigid decisions up front. I have encountered this over and over again.

I am happy to admit it's an inadequacy in object orientated design on my part, and if somebody were to suggest approaches that helps mitigate this problem I'd be very happy, but I do wonder whether it's an inherent property of the whole approach.


I agree that hierarchy-based OO can introduce real overheads. Favour composition over inheritance, and all that.

Having said that, I believe the problem is exacerbated because developers tend to worry too much about the structure of data from some arbitrary point of view. Put another way, we don’t tend to focus on how the data will be used in specific contexts, and therefore we don’t actively structure our data to be helpful in those contexts, even if each context is well defined and known to be relevant, unlike whatever “natural” structure we instinctively impose.

In your particular example, my first questions would be about how ISIN data is going to be used: where is the value for each security originally determined, where is it looked up later, what kind of decisions are made based on it, and so on. My next questions would probably be about why securities that are used in that way are being stored and manipulated with securities that aren’t. If there is no need to use both kinds of data at the same time, do the representations of the different types of security need to have related types in the code, or is that just an arbitrary decision we have made because it feels natural and in accordance with our view of the real world? Does a security even need to wrap up all of these properties in a single object, or are we really dealing with two or more distinct ideas that just happen to relate to the same real world activity at some point?

It’s not possible to answer questions like these without context, but so often with OO, we instinctively dive in and start identifying the nouns first, without considering the verbs that go with them.


This isn't really an OO problem. You can have similar troubles in a language with no static typing and no type hierarchies because you still have clients with expectations about the contents of a particular field.

A published API is a contract. Changing contracts is painful. There is no silver bullet.


You might have been able to deflect more of this if you had made up a new type of security that broke the rules (something nobody could have expected), however I thought your example illustrated the issue very well. For me it is especially common to run into the field that could never be null but now is scenario.

I liked your article a lot, very nice write up. I tend to lean towards the idea that there may not be much of a solution for this. But it's better to look for one than to just give up!


In my experience modifying existing C#/Java in such a manner is not a big deal since the type system and the language enable extremely powerful refactoring tools like Resharper.

But your point is fair. It is a tradeoff between flexibility and guarantees of strong, static typing -- a tradeoff that's a no-brainer in my opinion.


I feel you have missed the point of the article by criticizing the example. The suggestions you mention are discussed as possibilities, and his 'security is Option' is shown to give an example of bad code that arises during the quick fix process.

The point is that these situations are common and it would be nice if your language made it easier to adjust your object structure when needed.


> How would functional programming solve the problem?

In a language like ML or Haskell, it simply wouldn't compile until you fixed all the uses of Isin. By itself, it wouldn't solve the problem so much as force you to solve it before running it again.

Haskell and ML lack intrinsic subtyping. I don't know what you'd wind up with, but it would definitely feel a lot more explicit. I suspect if you followed a no-inheritance/many interfaces regime in C# you could port it across fairly straightforwardly to a typeclass-based implementation in Haskell.

I'm studying Smalltalk now and I actually am more interested in what the solution would look like without accessor methods. I do OOP professionally and FP on the side, but I don't think Java encourages good practices; everything winds up being a bean, which is essentially a struct. I think if OO principles were truly and seriously applied there would not be direct access to the Isin field (or any other field) from all over the codebase, those accesses would instead be somehow made into responsibilities of the owning class.

It's interesting to me because I think OO without encapsulation ports over fairly nicely to ML and Haskell, and OO with encapsulation should port over fairly nicely to Haskell with type classes. The trouble is always inheritance. But that turns out to be trouble in OO languages as well, so maybe it's a wash.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

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

Search: