• BorgDrone@lemmy.one
      link
      fedilink
      arrow-up
      3
      ·
      11 months ago

      In most programming languages data has a type. You can think of it as the ‘shape’ of the data. For example: you have an ‘integer’ type which can contain whole numbers, a ‘floating point’ type which can contain fractional numbers, a ‘string’ type which can contain text, etc.

      These simple types are called ‘primitive’ types, they are built into the language itself.

      Usually, you can also define your own types, which are made up of the primitive types, for example: you can have a ‘car’ type:

      class Car { 
          float maximumSpeed;
          int numberOfPassengers;
          String brand;
          String model;
      }
      

      Meaning any piece of data of type ‘Car’ has a maximum speed, number of passengers, brand an model.

      Now languages like Java have so called static typing. You declare something to be a car, and the compiler knows that a car has these properties. This is used in a lot of places. Variables have types, parameters passed to a function have types. The return values of functions have types, etc. Static typing means you always know exactly what type of data you are dealing with.

      Ducktyping is the exact opposite. The term comes from ‘if it walks like a duck and quacks like a duck, it’s probably a duck’. In a ducktyped language you don’t declare what type something is, you just use the data as if you know what type it is, and if it’s the correct type, it works. If it’s not, things might break.

      In a statically typed language it is impossible to use the wrong type, this is enforced by the compiler. In a ducktyped language this is impossible, as the types are not declared. So if a function expects a ‘Car’ as a parameter, and you pass in a ‘Horse’ instead, in Java you would get an error when trying to compile this code. In Python it would just run it. This may be fine. A horse may also have a maximumSpeed and if you try to read that it would work. But when you try to access something a Horse doesn’t have, like the ‘brand’ property, things go tits up.

      The main problem with this is that you only see this if you happen to run that specific bit of code in that specific situation. It may never happen during testing. Worse, if you change anything in ‘Car’ you don’t necessarily catch all the problems this causes. Say you rename ‘numberOfPassengers’ to ‘passengerCount’, in Java any code that still tried to access ‘numberOfPassengers’ would fail to compile, you’d immediately get an error. In Python you wouldn’t spot this problem at all until it’s too late.

      The advantage of ducktyping is that it’s less verbose, you can whip something together quickly without having to think too much about the types. For a small simple program this is perfect, but the larger your codebase gets the harder it becomes to manage this. You can’t oversee the whole codebase anymore, mistakes happen and the compiler won’t catch them.

      You can mitigate it a little, for example by writing lots of automated tests, but you really shouldn’t have to. A static type system prevents a lot of dumb mistakes from being made.