Live data from Hacker News

Don't Be Afraid of Types

lmika.org

51–60 of 233 posts

Re: Don't Be Afraid of Types

#51
post #4

The issue is names. Every darn little thing in Java needs a name. If there is no good name, that's a hint that maybe you don't need a new type. Obligatory Clojure example: (defn full-name [{:keys [first-name last-name]}] (str first-name " " last-name)) This defines a function named `full-name`. The stuff between [] is the argument list. There's a single argument. The argument has no name. Instead it is using destruct…

This sounds like passing JS objects around and having dependencies between caller and callee on their content being undefined and assumed. I can't think of much worse than that for anything other than a trivial codebase.

At least in Javascript you have JSDoc.

Re: Don't Be Afraid of Types

#52
post #49
post #48

Earlier quoted context omitted.

It is not like they are sworn enemies, but as messages can originate from outside the program, they cannot be typed statically. It is impossible to know what types will appear before runtime. For messages that originate from within the same codebase, you can, perhaps, start to layer static typing on top, but it can only be a partial solution as it remains that messages can come from other sources.

Then we are talking about distributed computing, and nothing will help you understand that glob of undefined bytes. This has nothing to do with OOP.

> Then we are talking about distributed computing

You must have a funny definition of distributed computing, then. OO never really caught on, probably because accepting "globs of undefined bytes" is kind of sucky, but we see some examples in the wild. Interface Builder is probably the best example of where we really leaned into OO, orienting a program's UI objects from externally defined messages. I'm not sure what building user interfaces has to do with distributed computing, but... I guess?

Re: Don't Be Afraid of Types

#53

Earlier quoted context omitted.

Definitely. If you have functions that only do one thing and are only called a few other place in the code, then by all means, name them explicitly. And I'd rather see that than a bunch of the same inlined anonymous function. I'm not really knocking the naming patterns as much as the data/logic patterns that required them. Factories are not a good thing. They usually imply that globals need to hold references. Obviou…

> Factories are not a good thing. They usually imply that globals need to hold references. No. Your statements are fundamentally wrong at many levels. Factories are tools to instantiate objects of a specific type a certain way. They are constructors that don't suffer from the limitations of constructors. A factory does not impose any requirement on object life cycle.

correct. i chuckle when someone talks so authoritatively on a topic they didn’t try to fully understand in the first place.

Re: Don't Be Afraid of Types

#54

> That’s what the type system is for: a means of grouping similar bits of information into an easy-to-use whole. While types can be used for that, they are a much broader concept. I would say the general purpose of types is to tell apples from oranges.

not to mention having some actual confidence when making changes to a project! especially one you didn’t author.

Re: Don't Be Afraid of Types

#55
post #52
post #49

Earlier quoted context omitted.

Then we are talking about distributed computing, and nothing will help you understand that glob of undefined bytes. This has nothing to do with OOP.

> Then we are talking about distributed computing You must have a funny definition of distributed computing, then. OO never really caught on, probably because accepting "globs of undefined bytes" is kind of sucky, but we see some examples in the wild. Interface Builder is probably the best example of where we really leaned into OO, orienting a program's UI objects from externally defined messages. I'm not sure what b…

"Messages that originate outside of the program" is distributed computing, regardless of it is on the same computing node, or across the network.

Multiple processes are involved, giving meaning to a byte stream.

I am quite sure Interface Builder has enough Objective-C type definitions, as does Portable Distributed Objects.

Additionally, those mapping definitions on the UI are nothing else than a type system powering the whole experience.

Re: Don't Be Afraid of Types

#56
post #2

my code became much easier to maintain once i stopped thinking of it as writing "algorithms" and "processes" and started thinking of it as a series of type conversions. structuring what lives where became easier, naming things became systematic and consistent, and writing unit tests became simple.

I agree; in my experience, pretty much everything is ETL. We take data from one thing, change it a bit, and put it somewhere else. Sometimes, as a treat, we take data from two things, put them together, and then put that somewhere else. Frontend, backend, databases, services, reports, whatever - ETL. In that context, the types and transformations between types are the most important feature. (Everything is actually C…

I remember working on an ETL pipeline in Airflow years ago and thinking: "we're defining and programming an abstract computer".

I guess with general computers everything we do is basically defining nested specific computers. That's, I think, the insight behind SmallTalk and the original concept of objects it used: the objects were supposed to represent computers and the message passing was an abstract network layer.

Re: Don't Be Afraid of Types

#57

Earlier quoted context omitted.

Definitely. If you have functions that only do one thing and are only called a few other place in the code, then by all means, name them explicitly. And I'd rather see that than a bunch of the same inlined anonymous function. I'm not really knocking the naming patterns as much as the data/logic patterns that required them. Factories are not a good thing. They usually imply that globals need to hold references. Obviou…

> Factories are not a good thing. They usually imply that globals need to hold references. No. Your statements are fundamentally wrong at many levels. Factories are tools to instantiate objects of a specific type a certain way. They are constructors that don't suffer from the limitations of constructors. A factory does not impose any requirement on object life cycle.

How you use a factory matters. A factory that sits as a static function inside the same class it's creating is one thing. It may just be a nicer interface to instantiate the class than the constructor itself.

On the other hand, it may do something with the object it's instantiating before passing it back. Such as putting it into global scope, or tying it to something outside its chain. Factories that sit outside the class file are often prone to all kinds of grotesque later mucking-with that causes the instantiated object to bind to other scope, and never be properly garbage collected. That's what I'm talking about.

Build better constructors and you won't usually need factories. If you need factories as an API, build them next to the constructor.

Re: Don't Be Afraid of Types

#58
post #2

my code became much easier to maintain once i stopped thinking of it as writing "algorithms" and "processes" and started thinking of it as a series of type conversions. structuring what lives where became easier, naming things became systematic and consistent, and writing unit tests became simple.

This resonates strongly! In Python, I often now find myself declaring Pydantic data structures, and then adding classmethods and regular methods on them to facilitate converting between them.

It makes for great APIs (dot-chaining from one type to another), well-defined types (parse, don’t validate) and keeps the code associated with the type.

Re: Don't Be Afraid of Types

#59
post #42

Earlier quoted context omitted.

The whole point of static typing is to ensure that runtime behavior is consistent with what gets passed. Right? The beauty of a typed OO language (like AS3 or TS) is that you immediately know if you might be referencing something using the wrong type. The only major language where every variable is cast/guessed in message passing at runtime is in naked Javascript, where everything's type is any/wildcard. It's such a…

> The whole point of static typing is to ensure that runtime behavior is consistent with what gets passed. Right? More or less. While the whole point of object-oriented programming is that behaviour is defined at runtime through the passage of messages. The messages may originate from the very same codebase, but not necessarily. Consider something like NeXT's Interface Builder, which relied heavily on injecting messa…

For the way you think about and reference data (if you can ensure type safety). To me, the advantage of OO is to give data objects methods so you can extract or modify what you want, how you want. The confusion that seems to arise is when coders think that objects and classes should "do things" or "make things". Anything that can be static, should be static. And anything that can be instantiated directly, should be instantiated directly. Factories and singletons should always be viewed as compromises against the nature of OO languages, and their presence minimized.

Take a particle system. Let's say each particle is an instance of a class with velocity and position. An attractor/repeller is also an object with V/P and some other features. These could all just be a [x,y,vx,vy,u,v,w] array that some global functions operate on, but then you'd lose inheritance as well as readability. The thing that runs that particle system on a loop, which manages all those tiny objects? It doesn't need to be its own object. Tie the delta function to the main timer for your game. And the main timer for your game? It shouldn't have multiple instances, right? It's about as central to Main() as anything else. There are lots of things in code that there should only be one of. Trying to shoehorn those things into objects and classes is where OO goes wrong and you end up with multiple timers or things that aren't expunged from memory.

However: Is it nice to manage an array of Particle objects with .x .y .vx and .vy, and some nifty methods to get and set those? Instead of writing that code to crunch through the same data on a flat 1-D array of all particles? Yeah. That's the point of OO.

Re: Don't Be Afraid of Types

#60
post #50
post #9

Earlier quoted context omitted.

> Every darn little thing in Java needs a name. Don't all types need names, regardless of what language you use? Look at typescript, and how it supports structural typing. They don't seem to have a problem with names. Why do you think Java has that problem when nominal type systems simplify the problem? > There's no need to declare a type ObjectWithFirstNameAndLastName. It would be quite silly. Naming things is hard,…

> Don't all types need names, regardless of what language you use? No. - In very dynamic languages (like javascript), most types arguably don't have names at all. For example, I can make a function to add 2d vectors together. Even though I can use 2d vectors in my program, there doesn't have to be a 2d vector type. (Eg, const vecAdd = (a, b) => ({x: a.x+b.x, y: a.y+b.y}) ). - Most modern languages have tuples. And tu…

The named integer range thing is interesting. I guess it depends on what you goal is. Could you use asserts? Could you wrap the integer in an object and embed the restriction logic there?
Post reply on HN