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

> new CartID(productID.toString());

With good data modeling and safety checks, this should fail: a product id and cart id should have some sort of distinguishing syntax (eg "P1234" vs "C1234") and so `new CartID("P1234")` will fail.

At some point, no sorts of type system can stop incorrectly implemented/specified logic. An even simpler example would be just passing some constant, valid, but not semantically correct string to the CartID constructor.

Your (a) and (b) solutions don't solve this. I could just as easily create a meaningless Cart object, or a meaningless ProductAddedEvent the same way you constructed that meaningless CartID.



As I said, if your data actually has internal structure that can be verified then the Type is meaningful. (Though that sort of prefixing introduces its own problems and I think most IDs just end up being UUIDs or URIs or numbers.) Otherwise you're just wrapping strings. The point here is that a Type represents data and behavior or, more formally, Types represent constraints over a space of data and behavior. Types that don't actually do any constraining are useless.

> I could just as easily create a meaningless Cart object, or a meaningless ProductAddedEvent the same way you constructed that meaningless CartID.

The problem here is not mixing up IDs. The problem is actually guaranteeing that the pre-conditions of addToCart() have been satisfied. Here, for example, addToCart() probably wants more than just a Cart and Product object, but a Cart and Product objects that have been persisted. Presumably the domain has been constrained so that you can't create meaningless objects. Otherwise what's the point of any object? If the only valid Cart and Product objects are those that can be retrieved from a persistent repository then, yes, this not only solves the trivial problem of mixing up IDs, but also the more valuable underlying problem that addToCart() is constrained to act on real, valid (according to the domain) Cart and Product objects.

In other words, this isn't really an issue of language design. And while there's a tendency to believe the language can solve every problems and that design patterns are a sign of language "weakness" the reality is developers that really want to solve these problems will have to think carefully about their domain and apply the appropriate design patterns.


>Types that don't actually do any constraining are useless.

Exactly!

I can make CartId/ProductId/WhateverId types that are just wrappers around String. But that's not actually using the type system to enforce correct behavior. Nothing in the type system prevents me from violating the invariants of my application.

I would only actually be using the type system, if my types were actually constrained so that only valid CartIds, that refer to real Carts, could be created. Then I would actually have a useful invariant, which the type system guarantees cannot be violated. (inasmuch as the validation step when creating CartIds is correct)


But aren't you then constrained until the end of time to ensure that cart ids and product ids are entirely disjoint? That's way too coupled for my little brain.




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

Search: