Live data from Hacker News

Don't Be Afraid of Types

lmika.org

181–190 of 233 posts

Re: Don't Be Afraid of Types

#181
post #177

Earlier quoted context omitted.

> Types are just a layer on top of your code that help enforce certain logical / mathematical properties of your code; those that your particular type system enables you to constrain. I don't know if I really agree with that. It seems to presume the default form of data is a map and you constrain that down to a specific set of fields. (Or similar logic over void pointer spaghetti.) If you build up a record type from…

No, you're really adding a constraint. You're adding a description of what exactly a piece of data represents, allowing the compiler or interpreter to limit the ways in which you can use it. The form of data in a computer is simply a sequence of binary information. It is up to you as a programmer to decide what it represents. In some cases, you can use a type system to have that automatically enforced in part. It's i…

> You're adding a description of what exactly a piece of data represents, allowing the compiler or interpreter to limit the ways in which you can use it.

Let's say I'm making a new record type with a .firstname field.

And let's say I'm not declaring what data type is stored in the field. Zero description or constraint is happening there.

The .firstname field itself was unrepresentable before I added it. There is no previously existing concept of accessing a .firstname field that I am constraining.

In this scenario, my language doesn't have access to raw memory, and even once I create this record type I don't know how it's going to be stored in memory. So I'm not constraining raw pointers into organized records because there are no pointers at all. I don't have raw byte access like in your HTTP example.

In that scenario, what am I constraining? What is the unconstrained version?

Re: Don't Be Afraid of Types

#182

People might be afraid of types because in OOP land there's the idea that types aren't mere containers for data. You have to use encapsulation, inheritance and polymorphism. Fields and properties shouldn't have public setters. You assign a value only through a method, otherwise you make the gods angry. You have gazillions of constructors, static, public, protected, private and internal. And you have gazillions of met…

    > because in OOP land
Speaking on behalf of enterprise CRUD devs (the vast majority of programmers), the Java POJO (pure data struct) is alive and well.

Re: Don't Be Afraid of Types

#183
post #9
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…

> 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,…

I frequently use anonymous types in my unit tests in Go. I create a custom type describing the inputs, behaviors and expected outputs of a test case. I create a collection of these cases, and use Go's standard library testing package to run the test cases concurrently scaling to the CPU's available threads.

Here's a simple example: https://github.com/dharmab/skyeye/blob/main/pkg/bearings/bea...

Re: Don't Be Afraid of Types

#184
post #172
post #158

Earlier quoted context omitted.

Your Point example is indeed good, it shows one of the drawbacks of small 'proper' objects. How do you handle the case of offsetting thousands of points with a single operation, which in most cases will make sense and is readily vectorizable? It's better to expose the internals and use external functions here. There's probably a deeper question, how to make objects 'transposable' in general case (like going from row-…

Honestly I wouldn't think much about offsetting thousands of points in my normal work. I'd expect that the compiler would do a good enough job of optimizing it and it's just as parallelizable (if necessary) as using a static method. Here I'm comparing against a static OffsetPoint(startPoint, x, y) type function. I don't see a performance difference there. But you're right that it's commonly nice to operate on sets of…

This conversation thread reminds me of the very interesting and insightful talk here: Klaus Iglberger “Free Your Functions!” [video] https://www.youtube.com/watch?v=WLDT1lDOsb4.

Re: Don't Be Afraid of Types

#185
post #145

Earlier quoted context omitted.

I don't think this is what lasagna means. Lasagna is when you have your software organized in layers. In other words instead of having a big ball of mud where A calls B calls C calls A calls C calls B you have layers (like in lasagna) so that A calls B calls C and you keep your code base so that classes/modules/types that are in the lower layer do not depend on or know of the anything above them and the dependencies…

Not trying to be funny, but "Ravioli code" might be closer: https://stackoverflow.com/questions/2052017/ravioli-code-why... https://en.wikipedia.org/wiki/Spaghetti_code#Ravioli_code A related principle that I don't think is talked about enough is "locality": I'd rather have all the code about one feature in one file or close together, rather than it strewn across files where it's harder to read and understand as a wh…

    > Traditional Java was notorious for being the opposite of this.
Is modern Java better? If so, why? Also, what languages do it better than Java and why? Any as old as Java that do it better?

Re: Don't Be Afraid of Types

#186

People might be afraid of types because in OOP land there's the idea that types aren't mere containers for data. You have to use encapsulation, inheritance and polymorphism. Fields and properties shouldn't have public setters. You assign a value only through a method, otherwise you make the gods angry. You have gazillions of constructors, static, public, protected, private and internal. And you have gazillions of met…

Inheritance is one way to achieve polymorphism. it is not mandatory for OOP. Unfortunately YES, because of "Java Entreprise" pushed by consultancies 15 years ago, a lot of developers insist on encapsulating everything, even when it's redundant. Fortunately, Java is a better language today.

    > a lot of developers insist on encapsulating everything, even when it's redundant.
Can you give an example? 15 years ago was 2010 and Java 8 was already released.

    > Fortunately, Java is a better language today.
In what ways? To me, it has barely changed since JDK 8 when it got lambdas. To be clear, the JVM is leaps and bounds better each long term supported release.

Re: Don't Be Afraid of Types

#187
post #50

Earlier quoted context omitted.

> 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…

"Most modern languages have tuples. And tuples are usually anonymous." Sure! And I LOVE ending up with var names that are always Item1 and Item2... Very descriptive!

Nobody’s saying anonymous tuples are necessarily a good idea. Just that lots of languages provide them.

Re: Don't Be Afraid of Types

#188
post #7
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…

In Python you're describing a Protocol. It's actually super reasonable to have a ObjectWithFirstNameAndLastName noun like this. You don't ever need to construct one but you can use it in the type slot and objects you pass in will be checked to conform. You see all kinds of weird specific types floating around the standard lib like this for type hinting. Duck typing is great, what's even better is documenting when whe…

I think protocols have two major drawbacks regarding readability and safety. When I have a protocol, I cannot easily find its concrete implementations, so it becomes harder to see what the code is actually doing. As for safety, protocols have no way of distinguishing between

  class Command:
    def execute(self) -> None:
      # some implementation
and

  class Prisoner:
    def execute(self) -> None:
      # some other implementation
The implementor of the Prisoner class might not want the Prisoner class to be able to be slotted in where the Command class can be slotted in. Your type checker will be of no help here. If you use abstract base classes, your type checker can prevent such mistakes.

So when it comes to your own code, the drawbacks of the structural Protocols in comparison the nominal ABCs are pretty big. The pros seem non-existent. The pro, I guess, is that you don't have to type the handful of characters "(Baseclass)" with every concrete implementation.

But they do have one major advantage: if you have third party code that you have no control over, and you have some part of this codebase that you want to replace with your own, and there's no convenient way to do something like the adapter pattern, because it's somehow a bit deeply nested then a Protocol is a great solution.

Re: Don't Be Afraid of Types

#189
post #153

Earlier quoted context omitted.

Objects are famously bad at (relational) databases, hence a near universal loathing of ORMs.

No, just putting the results in a set of objects as boxes and move them along. I don't use ORM layers. Just put the returning data from the DB directly into their neat boxes, string them along in a vector, and pass along. I also write my templated queries myself and talk with the server directly. No need to go "FizzBuzz Enterprise Edition" for a simple task.

When the data you need isn't entirely contained w/in those "neat boxes" you realize quickly the error was trying to force those "neat boxes" onto your data model.

Re: Don't Be Afraid of Types

#190

People might be afraid of types because in OOP land there's the idea that types aren't mere containers for data. You have to use encapsulation, inheritance and polymorphism. Fields and properties shouldn't have public setters. You assign a value only through a method, otherwise you make the gods angry. You have gazillions of constructors, static, public, protected, private and internal. And you have gazillions of met…

In that setup, how do you write a test which acts against a mock version of your API client (a static function in your proposal?)

Generally, avoid mocks.

Run a copy of the server in a container, run client E2E tests against it.

Post reply on HN