[HN Gopher] Types are a basic tool of software design (2018)
       ___________________________________________________________________
        
       Types are a basic tool of software design (2018)
        
       Author : gus_leonel
       Score  : 87 points
       Date   : 2024-12-31 10:00 UTC (3 days ago)
        
 (HTM) web link (www.tedinski.com)
 (TXT) w3m dump (www.tedinski.com)
        
       | karmakaze wrote:
       | (2018) btw.
       | 
       |  _I saw this much earlier in the day and dismissed it. I just now
       | read more of it. I was first off-put by the title, but then it
       | goes on to say:_
       | 
       | > [...] design is about everything that's leftover after we
       | remove all the function bodies. It worth taking a moment to think
       | about what that looks like. Here are some of my own immediate
       | thoughts: 1. Everything that's left is just types. [...]
       | 
       |  _Which reaffirms my suspicion that "Types!" are this writer's
       | hammer for all of programming's nails, or possibly a click-bait
       | writing device. There's probably a better article in here trying
       | to get out as the end notes mention. [Maybe read them first.]_
       | 
       |  _But I couldn 't even agree with the first one:_
       | 
       | > I meant for the main point of today's essay to be universal:
       | hence my emphasis that types are central to design even in
       | dynamically typed languages. [...]
       | 
       |  _I can 't say I've ever considered types/signatures when
       | sketching out a design. That comes much later in prototyping and
       | actual implementation--I suppose if I used Haskell that might be
       | different._
        
         | nightski wrote:
         | I am skeptical. You don't even know if a relevant piece of data
         | is say a number or text before you start writing out code? You
         | don't think at all about how you will group data together? You
         | don't think about the operations that will be performed on that
         | data and how they will transform it?
         | 
         | What do you think about when it comes to design?
        
           | acchow wrote:
           | Location of data, policies, cross-cutting concerns,
           | latency/performance requirements, etc.
           | 
           | "Much later" is probably an exaggeration. You get to types
           | "soon after" the initial design.
        
             | qayxc wrote:
             | Types are a useful design tool to explore the problem
             | domain first, while the rest are details that emerge from
             | that. Sure, if one starts with architecture, you're right.
             | The software _architect_ needs to consider these first. The
             | programmer on the other hand ideally expects those as
             | inputs.
             | 
             | When tasked with wearing on multiple hats (architect,
             | programmer, user), I agree with your point. From a
             | programmer's point of view, however, (abstract) types are
             | IMHO indeed a much more useful tool as they cover many of
             | the other concerns (policies, performance, etc.), too.
        
               | acchow wrote:
               | In my experience, a software engineer wears all the hats
               | nowadays. Even crossing into product design and user
               | experience.
        
             | nightski wrote:
             | It's interesting that you think about those things without
             | even understanding how you are going to solve the user's
             | problem first. Aka functional requirements.
        
         | packetlost wrote:
         | I find this really hard to believe to be honest. Even dealing
         | with things as rudimentary as a file handle are really thinking
         | about a type of some abstract thing, even if you don't really
         | conceptualize it as such. Types are _the_ way to put a name on
         | that abstract classification, so in dynamically typed languages
         | even the name of a variable or function assigns a
         | classification to the data it holds /returns, even if it's only
         | really enforced by the programmer.
         | 
         | There are basically no untyped programming languages for a
         | reason, types are a fundamental concretization.
         | 
         | In fact, I would argue there is no such thing as untyped
         | programming, there's just different degrees to which the
         | programmer is the enforcer of correctness.
        
         | oh_my_goodness wrote:
         | Sure, I think the author overstates his/her case and "finds the
         | One Ring". But it's not a dumb article. "Design is everything
         | that's leftover after we remove all the function bodies" seems
         | like a useful perspective.
        
           | slowmovintarget wrote:
           | Except it's not. The word "design" originated from the notion
           | of marking out or pointing out. To do it well is to take the
           | problem apart into small challenges that can be solved, with
           | a plan on how to make the pieces hang together again.
           | 
           | Design often includes algorithms, which don't devolve merely
           | to types. So this statement only makes tangential sense if
           | all you're ever building is CRUD applications.
        
         | boscillator wrote:
         | I pretty much always start with types/signatures when sketching
         | out a design. I guess if there is a complicated algorithm, I
         | might start with pseudo code for it, but even then, I probably
         | want to start with what it's inputs are and what it's outputs
         | are.
        
       | oh_my_goodness wrote:
       | I'm glad we finally found the 1 basic tool of software design. We
       | can for sure stop thinking and arguing about that.
        
       | seanwilson wrote:
       | I love this before/after example of TypeScript being removed from
       | a library as a clear illustration that only occasional simple
       | type annotations are needed:
       | https://github.com/hotwired/turbo/pull/971/files
       | 
       | Looks like so much useful documentation for understanding the
       | code, assistance for refactoring, and static checking (which are
       | like always running, fast and exhaustive unit tests for free) for
       | a modest amount of type annotations that each person on the team
       | would need to recreate in their heads anyway. Static type
       | checking is so useful for catching runtime errors to do with
       | optional values and index/key not found error too, that always
       | create a load of edge cases.
       | 
       | Editing JavaScript with no types is scary, especially when you
       | didn't write it. You're mostly guessing what the types must be
       | and hoping your running code exercises enough edge cases to catch
       | any problems. "You should write more tests" as an alternative
       | rings hollow for me because (for the things they will check for
       | you) types are more concise, exhaustively check all values, are
       | ran continuously, are fast, aid with automatic refactoring,
       | document the code in the same file its in, and will locate exact
       | snippets that are causing errors. More often than not, test
       | mostly check happy paths, aren't even close to as exhaustive, and
       | nobody is writing tests that check every combination of function
       | parameters being null vs non-null, string vs number etc. (which
       | would be a huge amount of noise in your test suite that would
       | slow down refactoring too). Types are a compliment to tests as
       | well, not an alternative.
       | 
       | I can't relate to arguments about types getting in the way (as
       | long as you avoid trying to get too clever like with complex
       | generics and TypeScript conditional types). Usually when this
       | happens, it's because it's hard to reason the runtime edge cases
       | in your own head and there's probably a simpler way to write it.
       | I'd love a good non-niche example to the contrary. Worst case in
       | TypeScript, you can use `any` as an escape hatch anyway so as
       | long as you can add types to most of your program it's not a
       | strong reason against for me.
        
         | benatkin wrote:
         | That PR is great. Not only do they get rid of TypeScript, they
         | get rid of prettier and some gratuitous trailing commas.
         | https://github.com/hotwired/turbo/pull/971/files#diff-865b8f...
         | 
         | I'm not joking. I prefer the _after_.
         | 
         | Edit: thanks. Yes, commas, not comments.
        
           | lofenfew wrote:
           | s/ent/a
        
           | vallode wrote:
           | I could not disagree more, but I am obviously open to it
           | being a personal preference. I've spent months updating
           | JavaScript codebases that are between 3 and 5 years old, most
           | of them written with vanilla JavaScript. A _few_ of them were
           | written with TypeScript at least partially and those files
           | were the least mentally taxing to upgrade.
           | 
           | Some of the codebases had tests, a good chunk of which could
           | (and were) eliminated simply by using TSC as part of the
           | build process. I think allowing the compiler and tooling like
           | prettier to make choices for you leaves more space for you to
           | think about the problem, not the myriad of problems _around_
           | it.
        
           | Shacklz wrote:
           | Funny, I have exactly the opposite feelings.
           | 
           | I've worked on dynamically typed code-bases in the past, and
           | also on code-bases without formatters like prettier... and
           | I'm not going back there.
           | 
           | So many odd bugs can be avoided simply by taking a little bit
           | of time and declaring some types. It doesn't have to be a
           | super fancy type-system (I actually prefer if it isn't), but
           | I really want to know whether something is expected to be a
           | string or a number, or what properties an object can be
           | expected to have, or what values a literal can accept, and so
           | on. It's just so frustratingly time-consuming to figure out
           | in hindsight. And all for some person's odd perception of
           | simplicity.
           | 
           | Same for formatters - all the squabbling over some personal
           | preferences on how code should be formatted. Hell no. Let's
           | install some opinionated formatter and let it do its job, I
           | want to tackle more interesting problems than yet another
           | narrow-minded discussion about necessity of semicolons,
           | placement of whitespace or line-length.
           | 
           | I'm at a point where I straight-up refuse to work with people
           | who prefer to work that way; or at least require them to be a
           | few departments away from me. They can be programming gods;
           | if they can't be arsed to type their code so I can
           | immediately grok it, they can program elsewhere.
        
             | n144q wrote:
             | Same.
             | 
             | I sometimes write TypeScript for 2 hours straight without
             | actually running the code or any unit test, and it would
             | _just work_ -- the return value is exactly what you want. I
             | don 't think I can do that for JavaScript for more than 15
             | minutes even though they are the "same language".
        
           | PittleyDunkin wrote:
           | What's the benefit of removing the explicit typing? It
           | strikes me as hamstringing readability of the code. This just
           | feels like giving up and calling the status quo "beautiful"
           | or something.
        
             | bnetd wrote:
             | To reinvent it.
        
               | benatkin wrote:
               | People tried to argue that in the PR, suggesting to
               | change variable names.
               | 
               | This one: https://github.com/hotwired/turbo/pull/971/file
               | s#r1317386731
               | 
               | > function buildFormData(formElement: HTMLFormElement,
               | submitter?: HTMLElement): FormData {
               | 
               | > It might be useful to know that submitter is optional
               | argument here.
               | 
               | > How would one express that? The variable now needs to
               | be renamed?
               | 
               | And two lines later:
               | 
               | > const name = submitter?.getAttribute("name")
               | 
               | It's already easy to see that submitter is optional.
        
               | lelandbatey wrote:
               | Only easy to see that it's optional if you read the
               | source code vs. looking at the auto definition in your
               | IDE/in autogenerated documentation.
        
           | superb_dev wrote:
           | Even with the find/replace errors that seemingly got merged?
           | This PR feels like it was so rushed
        
           | madeofpalk wrote:
           | I can't imagine caring that much about trailing commas. The
           | point of a tool like prettier is to not sweat such irrelevant
           | details.
        
             | slooonz wrote:
             | Trailing commas actually have an important role.
             | 
             | Let's say you have some code :                 const foo =
             | {         x: 1,         y: 2,       };
             | 
             | and you want to add a field :                 const foo = {
             | x: 1,         y: 2,         z: 3,       };
             | 
             | Without trailing commas, the diff is                 - y: 2
             | + y: 2,       + z: 3
             | 
             | With trailing commas :                 + z: 3,
             | 
             | The second diff is actually much clearer at what's
             | happening.
             | 
             | This is why it irritates me when people forget the trailing
             | comma. It's not a problem in the moment. But I know it will
             | be a small but avoidable cognitive burden on the _next_ PR
             | (wait, why did  "y" changed ? Oh, right, it didn't).
        
               | fire_lake wrote:
               | Maybe diff should change to suit programs, rather than
               | programs change to suit diff.
        
               | benatkin wrote:
               | Indeed. That's why prettier ain't pretty.
        
               | slooonz wrote:
               | You want diff to know the syntax and semantics of every
               | programming language out there ?
        
               | benatkin wrote:
               | It would be like a syntax highlighter. It's doable.
        
               | slooonz wrote:
               | But diff does not exists in a vacuum. It would need to be
               | integrated to IDEs, editor, merge tools, PR tools. You
               | now have to have `patch` understand and depend on the
               | details of the syntax of your language. In a way that may
               | break between different versions of diff and patch. Not
               | even starting with variants of a language, different
               | interpretations of how to handle the preprocessor/macros
               | system, different editions of the same language.
               | 
               | All that, just to not have to add a trailing comma ?
        
               | benatkin wrote:
               | Most things like patch would still use line diff. I think
               | I would want this semantic diff in the merge request
               | review and the logs. It could have definitions
               | distributed with the syntax highlighters in language
               | plugins in an editor/IDE, git CLI, and git forge.
        
               | knubie wrote:
               | This is possible already with tools like difftastic.
               | 
               | https://github.com/Wilfred/difftastic
        
               | DarkPlayer wrote:
               | Difftastic would not solve the issue described by
               | madeofpalk because it still highlights the added comma.
               | You need a diff tool that can distinguish between
               | optional and required syntax. So far I am not aware of
               | any tool that supports this, except the one I am working
               | on (SemanticDiff).
        
               | madeofpalk wrote:
               | Sure, I can get behind that. That's why we just automate
               | these trivial things away.
        
               | Jarwain wrote:
               | I also like it because I can reorder items in an array
               | without having to also add/remove a comma!
        
           | motorest wrote:
           | > I'm not joking. I prefer the after.
           | 
           | Everyone likes the simplicity that comes with removing
           | guardrails, but when easily preventable problems happen
           | that's glanced over as an unavoidable fact of life.
        
             | knubie wrote:
             | > but when easily preventable problems happen
             | 
             |  _easily preventable_ is doing a lot of work here. This is
             | assuming the types are already written and never need to be
             | maintained. How often does the type checker catch a problem
             | with the code vs the type definitions themselves?
        
               | seanwilson wrote:
               | > How often does the type checker catch a problem with
               | the code vs the type definitions themselves?
               | 
               | All the time? I've worked on code bases with multiple
               | people without types, and whenever there's a place that
               | can produce e.g. "string or null" or when a key might not
               | be found in a collection, it produces edge cases
               | everywhere that don't get noticed outside of the happy
               | path, including after the code has been merged. You're
               | forced to simulate in your head all the code paths, and
               | remember which values might be optional which isn't
               | scalable.
               | 
               | Even typos like `object.detail.name` vs
               | `object.details.name` cause runtime errors, or calling a
               | function without the right number of arguments.
               | 
               | I don't understand how someone can dislike writing type
               | annotations so much that they're happy to have their time
               | wasted on some of the most trivial bugs you can think of
               | like this when automated assistance is right there. It's
               | like not wanting to use a spellchecker when writing an
               | article, or opting out of syntax checking code before
               | it's ran to me.
               | 
               | I get that problems with type definitions can be
               | frustrating but it's better than runtime errors, and
               | often indicates actual bugs, potential future bugs, or
               | weird code. I'd love an example here. 90% of type
               | annotation stuff I work with is mundane and simple (e.g.
               | strings, numbers, arrays, something optional, object with
               | basic fields) and is well worth the minimal effort. The
               | more complex stuff usually gives you protection from
               | tricky bugs so is worth the effort too.
        
         | plagiarist wrote:
         | > This one is interesting. I would have no idea what a
         | "submitter's" purpose is here with or without Typescript.
         | 
         | > I am excited to see how this code base changes without
         | Typescript. The "types" or what things are will have to be
         | communicated in some way. This may lead to very readable code.
         | 
         | This is funny to me. "If we don't have the compiler checking
         | types the developers will perfectly compensate with
         | documentation, an improvement." Maybe remove the unit tests as
         | well, then the developers will write accurate code.
        
           | marcosdumay wrote:
           | It's using that expendable developer time to free some
           | precious extra developer-machine-CPU time.
           | 
           | Who wouldn't want to spend some weeks or hard labor so their
           | computers can work for a few less seconds? Let's keep what's
           | really important in mind!
        
       | hyperhello wrote:
       | Grammar is the basic tool of writing. Atoms are the basic tool of
       | physics. Etc.
       | 
       | What I think this post is reaching for is not types, and it's
       | beyond even abstract data structures. It's really templates,
       | which is a general concept that gets used in every design
       | scenario. Numbers are templates, integers are templates, bits are
       | templates. We can describe how the idea works to each other and
       | partly to the computer but it's up to the programmer to animate
       | them.
       | 
       | Once you understand the concept you see it everywhere. Super
       | Mario is full of templates: you jump on an enemy's head, or
       | sometimes it doesn't work but gives you a clue to do something
       | else. Templates are nodes of understanding.
        
         | bromuro wrote:
         | I've lost you at the template part: do you mean _models_?
        
       | xvinci wrote:
       | > One of Haskell's most basic innovations (well, I'd guess it
       | probably wasn't first, but compared to other relatively
       | mainstream languages) was the ability to write the type of a
       | function separately from writing the function body.
       | 
       | Anyone familiar with the initial versions of C / C++? Both
       | languages have offerd the ability to define your function
       | signatures in header files for as long as I have known them, so
       | if you wished to separate from the actual function body you
       | should have been able to do that.
       | 
       | But then Haskell can hardly have been the first mainstream? But
       | maybe someone with more ancient knowledge could share some
       | insights - thx.
        
         | PittleyDunkin wrote:
         | I wouldn't characterize a forward declaration of a function as
         | a distinct definition of its types--any types in the forward
         | declaration must match those in the implementation; there's no
         | way to implicitly refer to the types used in the forward
         | declaration to ensure a single place of typing.
        
         | cess11 wrote:
         | Arguably COBOL has it with its data division, as does Ada.
        
         | codr7 wrote:
         | Common Lisp supports something along those lines, mostly for
         | optimization purposes.
        
       | bionhoward wrote:
       | Python does have something like interfaces and it's called
       | Protocols
       | https://docs.python.org/3/library/typing.html#typing.Protoco...
       | 
       | Other classes can count as implementors of protocols without
       | needing to subclass them, and static type hints will notify you
       | if you make a function which accepts a protocol as an argument
       | and pass something which doesn't implement it
        
       | cess11 wrote:
       | Could generalise it to 'data is the basic tool of software
       | design', then the article would have to muddle shape, structure
       | and type into a single type concept.
        
       | algorithmsRcool wrote:
       | I go a little back and forth on this with my experience in F#,
       | which relies heavily on inferred types. You can write _a lot_ of
       | F# before you need to add type annotations, but eventually,
       | things become a spiderweb. The key issue is when you make a
       | 'small' change to some method/value, the changes ripple through
       | the program creating confusing errors sometimes where the
       | compiler is trying to knit things together.
       | 
       | After a while, I found myself adding back types in a decent
       | number of places to "anchor" the type inference, indicating that
       | a certain type/signature is fixed and a change should be
       | carefully considered.
       | 
       | I still don't know how folks deal with these kinds of changes in
       | weakly typed languages without always allowing bugs to pour into
       | their code over time. But I do love the "move fast" and low
       | boiler-plate aspects of "typeless" coding.
        
         | scalaisneat wrote:
         | I agree with this sentiment but view it inherently as a feature
         | of languages like f# and Haskell - That small ripple at compile
         | times makes trusting refractors easier. After having
         | experienced this, languages like python become really
         | challenging to grok without heavy unit testing.
        
           | kibwen wrote:
           | There's also a middle ground which is to support function-
           | local type inference, but not inter-function type inference,
           | which guarantees that such an "anchor" is never all that far
           | away (especially never in another file). This is the approach
           | Rust uses.
        
         | MoreMoore wrote:
         | I think what a lot of people miss is that this ripple effect
         | always exists. Whether you have strong types or weak types,
         | it's hard and often impossible to avoid.
         | 
         | All strong types do is make it explicit at compile time (and
         | with static analysis), instead of leaving it to be discovered
         | in tests or at runtime.
         | 
         | This is why I'll use Python for small one-off scripts but
         | anything that will be in regular use I prefer to do in Java.
         | Even though I have many more years of experience with Python.
        
           | jonathanlydall wrote:
           | As someone who works in C# and TypeScript, I suspect that
           | people who work in weakly typed languages either:
           | 
           | - Don't have big projects.
           | 
           | - Have lots of unit tests to cover some of what a C# or Java
           | compiler would have caught through static analysis.
           | 
           | - Don't even consider doing certain kinds of refactoring
           | (which would be trivial on a strongly typed language) because
           | they have no way of knowing what will break.
        
             | leptons wrote:
             | 4th option, they are just better than you are at managing
             | dynamism.
        
               | jonathanlydall wrote:
               | Even ignoring for a moment that I consider being highly
               | practiced at dynamism a largely pointless skill while
               | strongly typed languages exist, sooner or later a code
               | base which is always growing will reach a certain size
               | where even the very best person in the world at dynamism
               | will have to resort to unit tests to cover what a
               | compiler can do for free, or just accept that certain
               | refactoring or changes to the code base are unreasonably
               | expensive to do with any reasonable level of confidence.
        
               | leptons wrote:
               | I'm the guy with a huge javascript codebase, written
               | before typescript existed, and I have none of the
               | problems you describe. Huge refactors are also not a
               | necessity in every codebase, if the code was written well
               | to begin with. And so far using typescript in other
               | projects has not produced the supposed benefits a lot of
               | people say are inherent with typescript. There is no
               | magic happening that saves me from writing bad code,
               | because I wasn't writing bad code before typescript.
               | Refactoring isn't all that difficult either, even without
               | tests. But I guess _YMMV_.
        
               | thfuran wrote:
               | Good code becomes bad when the requirements change
               | sufficiently in ways the original design didn't
               | anticipate.
        
               | leptons wrote:
               | Great, but that doesn't describe every Javascript project
               | or use of Javascript. If you're describing big changes,
               | chances are a refactor isn't what's needed, a rewrite is.
               | And even when requirements change, it doesn't mean
               | Javascript can't be refactored. It depends on the skill
               | of the team. If you want to hire idiots then you're going
               | to need more than strong types to get anything shipped. I
               | doubt types would really help that much in some places
               | because programmers love to invent their own footguns.
        
           | samatman wrote:
           | Is it really too much to ask to use the correct terms here,
           | static and dynamic typing?
           | 
           | Strong and weak are sort of coherent as a spectrum, but they
           | aren't a typology, and they do not in any sense or in any
           | case reduce to static vs. dynamic types. Conflating them is
           | not useful: I can make a good case that Julia's type system
           | is stronger than C's, but Julia is dynamically typed and C is
           | statically typed.
           | 
           | There's no reason to keep doing this. It's a malapropism, we
           | could just.. not say that. Especially in a thread which is
           | specifically about types.
        
         | kybernetikos wrote:
         | Having worked on a large js codebase back before typescript or
         | flow or the closure compiler existed, I found that the process
         | was not very different to any code - you check your
         | preconditions on entry to code that will be called from
         | elsewhere, it's just that those preconditions in a dynamically
         | typed language may include the types of your arguments. If you
         | do that, then type errors typically cause your code to fail
         | fast, often on first load, in easy to understand ways. Overhead
         | is just a couple of extra easy to understand lines at the top
         | of about half your functions (probably less boilerplate than
         | go's error handling forces on you).
         | 
         | Given the fantastic iteration speed that the Web platform had
         | (and still does to some extent) I didn't really miss a compiler
         | for catching errors. The main improvement is that IDEs find it
         | easier to support big refactoring.
         | 
         | I also worked on a mid sized scala codebase a little later on.
         | Scala is probably better now than it was then, but despite
         | (perhaps because of?) the cleverer type system, everything was
         | so slow that it actually took longer for many bugs to be
         | highlighted by the compiler than they would have been found by
         | hitting f5 in a browser window with a good js codebase. That
         | was when I realised that as a developer I care a lot about when
         | an error is highlighted in wall clock time and not at all about
         | which compiler phase it was discovered in.
        
         | titanomachy wrote:
         | I think Scala has a good compromise here, where all function
         | signatures require explicit types and (almost) everything else
         | can be inferred. Maybe F# does the same? I find that this is
         | enough "anchoring" to allow for sensible error messages most of
         | the time, although occasionally I'll sprinkle in more
         | annotations if the inferred types would be particularly
         | confusing to readers (usually because they're too general).
        
         | neonsunset wrote:
         | > You can write a lot of F# before you need to add type
         | annotations, but eventually, things become a spiderweb. The key
         | issue is when you make a 'small' change to some method/value,
         | the changes ripple through the program creating confusing
         | errors sometimes where the compiler is trying to knit things
         | together.
         | 
         | I found working with type inference being its own skill. If you
         | know how to place type annotations well, the ripple effect only
         | affects one or two callsites and then the type inference just
         | continues to infer what you meant in the subsequent code.
         | Though we may be approaching the structuring of the code
         | differently so YMMV. But I haven't had issues even with
         | complicated member constraints which replicate dependent
         | typing.
        
       | taeric wrote:
       | This is stretching the definition of "tool." I would go far in
       | agreeing that types are fundamental to the vocabulary of software
       | design. But calling them a basic tool feels off. Is akin to
       | saying rooms or units are a basic tool of building design. I can
       | see arguments for it, but tools typically refer to the various
       | things that actively do something. Hammers and such. Maybe a
       | level bar?
        
         | motorest wrote:
         | > This is stretching the definition of "tool." I would go far
         | in agreeing that types are fundamental to the vocabulary of
         | software design. But calling them a basic tool feels off.
         | 
         | Sometimes I wonder if this type of article is just a rehash of
         | object-oriented programming articles from the 90s where the
         | keyword "class" is search-replace'd by "type".
        
       | Waterluvian wrote:
       | I'm not sure if this is obvious to the average developer and I'm
       | late to the show, but a few years back things clicked for me when
       | I grokked that _types exist no matter how you feel about them._
       | 
       | You still have to reason about the types no matter what. But
       | writing it down empowers you to offload a lot of mental load to
       | the computer, asking it to check your work, give you feedback as
       | you go. It also communicates intent to other humans who read it.
       | 
       | One reason I like TypeScript is that there remains a, "just trust
       | me" escape hatch when I'm testing/hacking something and don't
       | want to "show my work" by writing out some complex type. (Funny
       | how "show your work" is something math teachers have to fight
       | many students to do. This feels like the same thing). But that
       | complex type always existed. You're just saying "trust me on
       | this." Writing it down doesn't conjure the type into existence.
       | 
       | Rust also clicked for me when I understood that it's really just
       | _more_ of the same thing: memory management, lifetimes, etc.
       | exist no matter what. But it offers a way to show your work,
       | formalizing intent, so that the checker /compiler can worry about
       | the boring problems for you.
       | 
       | In this sense, the issue is really about making decisions on just
       | how much "trust me on this" is appropriate.
        
         | fellowniusmonk wrote:
         | Mereological Nihilism demonstrates that most types are an
         | illusion.
         | 
         | Space, Time, Minds. Those exist. Probably :)
        
       | boscillator wrote:
       | A lot of people are complaining that this seems too "obvious" in
       | one way or another, but I think it can be useful to write down
       | and be explicit about such an important underlying fact of
       | programming. Completely understanding the types in your program
       | forces you to think carefully about the domain.
        
         | motorest wrote:
         | > Completely understanding the types in your program forces you
         | to think carefully about the domain.
         | 
         | Isn't it the other way around? Types derived from analysing the
         | problem domain? That's the basic premise of a bunch of software
         | design techniques.
        
         | leptons wrote:
         | I enjoy coding in assembly language, where types are not really
         | a thing. Yeah, it really forces you to think carefully about
         | the domain. I'm not talking about a little bit of in-line
         | assembly, I've written entire UI, device drivers, and
         | everything else in assembly - many thousands of lines of code.
         | Maybe this is why I don't feel like Typescript has solved
         | anything much for me when I work with front-end code.
        
       | game_the0ry wrote:
       | Since adopting typscript, the way I usual approach my development
       | is that I clearly define data types on ui and then the
       | implementation details tend to reveal themselves.
       | 
       | There is a quote I saw somewhere, forget where, but it was
       | basically: define your data structure and the algorithms will
       | reveal themselves.
        
         | motorest wrote:
         | > Since adopting typscript, the way I usual approach my
         | development is that I clearly define data types on ui and then
         | the implementation details tend to reveal themselves.
         | 
         | That is aligned with the basic premise of Domain-Driven design:
         | define a model of the problem domain, and everything else just
         | falls in place.
         | 
         | I wonder why these articles reinvent the wheel with functional
         | programming hand-waving when DDD has been screaming this for
         | years.
        
           | PittleyDunkin wrote:
           | > I wonder why these articles reinvent the wheel with
           | functional programming hand-waving when DDD has been
           | screaming this for years.
           | 
           | These are two different levels of abstraction. If you're
           | still enraptured by the fundamental mechanisms of computation
           | (i.e. functional programming) you're not going to see the
           | value in trying to figure out the best way to build via
           | composing mechanisms of computation, whether it's functional,
           | imperative, procedural, logic-based, lisp-based, object-
           | oriented, message-passing, whatever. There's a reason why
           | there aren't many DDD frameworks out there--it doesn't really
           | benefit from tying to specific
           | technologies/languages/ecosystems in the same way that the
           | culture of "build shit as fast as possible" attitude
           | dovetails well with the goals of Rails.
           | 
           | I don't see why this is surprising; people re-discover old
           | lessons daily, and petty details will always be conflated
           | with broader themes and patterns--it's just how the human
           | brain works. The discussion is what keeps us thinking about
           | those old lessons. This is just a person's blog, not a
           | journal trying to represent an industry.
        
         | jpitz wrote:
         | Could it be Linus Torvalds' "Bad programmers worry about the
         | code. Good programmers worry about data structures and their
         | relationships." ?
        
           | game_the0ry wrote:
           | Honestly, do not think so, but its close enough.
        
             | azornathogron wrote:
             | There's a well known quote from Fred Brooks too:
             | 
             | ""Show me your flowcharts and conceal your tables, and I
             | shall continue to be mystified. Show me your tables, and I
             | won't usually need your flowcharts; they'll be obvious.""
             | 
             | (Though from your description I suspect that's also not the
             | one?)
        
         | gonzus wrote:
         | Probably by Fred Brooks, as summarized by Guy L. Steele Jr in
         | https://dreamsongs.com/ObjectsHaveNotFailedNarr.html:
         | 
         | > Fred Brooks, in Chapter 9 of The Mythical Man-Month, said
         | this: _Show me your flowchart and conceal your tables, and I
         | shall continue to be mystified. Show me your tables, and I won
         | 't usually need your flowchart; it'll be obvious._ That was in
         | 1975. Eric Raymond, in The Cathedral and the Bazaar,
         | paraphrased Brooks' remark into more modern language: _Show me
         | your code and conceal your data structures, and I shall
         | continue to be mystified. Show me your data structures, and I
         | won 't usually need your code; it'll be obvious._
        
       | arialdomartini wrote:
       | I'm reading Type Driven Development with Idris and this post
       | really resonates with what I'm learning. Especially the idea of
       | writing down the function's type to be guided how to implement
       | it.
        
         | arialdomartini wrote:
         | PS: Type Driven Development with Idris is mentioned in the
         | final notes. OP, I could not recommend it more!
        
       | k3vinw wrote:
       | Is it too simplistic or abstract to think of types as merely
       | contracts?
        
         | TypingOutBugs wrote:
         | I think that works!
        
       | renox wrote:
       | > One of Haskell's most basic innovations [cut] was the ability
       | to write the type of a function separately from writing the
       | function body.
       | 
       | I don't get it, what's the difference between this and C's
       | function declaration?
        
         | xigoi wrote:
         | In C, you still need to write the types in the definition.
        
       | andsoitis wrote:
       | I really like the balance struck by Ada's type system, especially
       | Application-Defined types to model the problem domain -
       | https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Devel...
       | 
       | Other effective features of Ada's type system:
       | 
       | - type ranges
       | (https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Devel...)
       | 
       | - generalized type contracts using subtype predicates
       | (https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Devel...)
       | 
       | - attributes
       | (https://learn.adacore.com/courses/Ada_For_The_CPP_Java_Devel...)
        
       | ddyevf635372 wrote:
       | There are still so many devs who don't want to deal with types,
       | and they love Ruby and Python, as well as JavaScript without
       | types.
       | 
       | It is quite difficult to work on large Ruby or Python projects;
       | interfaces are not determined, and figuring out what's happening
       | is painful.
       | 
       | Still, so many devs love it, and they wanna keep working with
       | Ruby and Python in this way.
       | 
       | I kind of feel that experienced devs move on, and give up
       | projects without types.
        
         | bowsamic wrote:
         | These days most Python devs I know use types
        
         | neverartful wrote:
         | The funny thing is that even for devs who don't want to declare
         | their types will still have think about them to some extent.
         | Even if it's correcting run-time errors indicating that some
         | function or property doesn't exist for type 'X'. Plus, they get
         | to guess at the types that are expected for various function
         | calls in their own projects. Oh sure, you can add comments that
         | document it right above/below the function, but do you remember
         | to keep those up to date while you're in the middle of
         | refactoring?
        
       ___________________________________________________________________
       (page generated 2025-01-03 23:01 UTC)