I feel like all large Python endeavours eventually reach the point where they realize that Python sucks

@sir I think Python is only good up to 1000 lines of code. Beyond that, it becomes a mess.

@zachdecook @sir
Haven't done enough javascript to be able to tell, but my wild guess would be 50 lines of code.

@Wolf480pl

> Haven't done enough javascript

I have. Leaving aside the relative mess caused by module systems like , large code bases are actually very maintainable. I am currently working with two related code bases of similar complexity and size, one C++ and the other JS, and I find the latter much more pleasing to work with (minus NPM) in large part due to the duplication introduced by header / code files.

But as usual, it's horses for courses.

@zachdecook @sir

@0
Well, my guess of 50 was mostly a reaction to the plague of heavy websites which do in JS what could've easily be done in CSS. IIRC the original intended use of JS was a few lines of scripts here and there, not a big application with dependencies.

Maybe some projects of hundreds or thousands lines JS code can be maintainable, but I'd expect them to.have the same kind of problems Python has due to lack od static types.
@zachdecook @sir

@Wolf480pl

> I'd expect them to.have the same kind of problems has due to lack od static types.

And what problems would those be?

@zachdecook @sir

@0 @zachdecook @sir
that someone puts a null or None in a place where it's not allowed, but nobody notices until it's passed to the other end of the code which rightfully assumes it's not a null and tries to access its member and it crashes.

It happens at runtime.
Only under certain conditions.
And the stacktrace contains no information about the function which introduced the null.

And it's not just null. Same can be said about variables/arguments assumed to be an object implementing some interface, having a member of particular name, etc. If you accidentally put there an object that doesn't match such requirements, you're unlikely to get an error right away pointing you to the place where things went wrong.

Now, C is only slightly better in that regard, same with C++. But anything from Go to Haskell has a strong enough static type system to catch most of those things at compile time.

@Wolf480pl

I can't say that I've seen this to be a problem in practice.

Wrong typing falls under the more general category of wrong input and is addressed at that level by proper input validation.

@zachdecook @sir

@0 @zachdecook @sir
so, all of your functions validate their arguments, and wherever you call a function you validate if it returned the right thing?
Sounds like an extreme case of defensive programming that'd make your code unnecessarily repetitive, long to write, and hard to read

@Wolf480pl

1. Basically yes, that's it.

2. Basically no, I don't think so, why would it?

If you don't validate your inputs how do you avoid ?

@zachdecook @sir

@0 you:
1. Validate your inputs when they come from outside your program (from user, from files, from network, etc.)
2. Make types such that all valid inputs are of that type, and no invalid inputs are of that type. Any value of that type is valid by definition.
3. Validation in point (1) returns values of types from point (2) or error (eg. Maybe<ValidatedThing>, or Either<ValidatedThing, Error>) which you can then break down with a match statement.

@0
Besides, type annotations make a great documentation.

When you're modifying a program, and you wonder "what is this `peer` variable and how can I get an IP address out of it", you can either:

a) Not have documentation. You can trace through all the code to find where that peer thing could come from, all the way to constructor, to figure out that it has an `inet_address` property so you extract an IP like this: `peer.inet_address`

b) Have outdated documentation, which says that the `peer` variable should be a tuple of `(ip, port)`. So you think that the right way to extract IP address is `peer[0]` which then turns out to not work

c) Have types. (pls excuse invented syntax) The `peer` variable's type is declared in the function prototype 5 lines above like this: `peer: Connection`. You look at the top of your file, and see: `from .netutils import Connection`. So you know Connection comes from the netutils file in the current directory. You open that file, quickly find Connection's definition, and it truns out that it says:
```
class Connection:
...
inet_address : IPAddress
...
```

and now you know that `peer.inet_address` will exist, and will contain a valid IP address.

@0
And it will never get outdated, because if someone tried to change what's being passed to that function without updating the type annotations in all the relevant places, the compiler would complain.

@Wolf480pl

Yeah that addresses certain aspects of input validation, but by no means all.

Say that your ‘peer’ variable needs to be in your range and the latter can vary, perhaps even during runtime. All the static typing in the world is not going to help detect that situation so it is only an incomplete answer to the problem at hand.

I find it has its place but it's no silver bullet and can even introduce unnecessary complexity, e.g., in cases a duck typing approach is better suited.

@0 from my experience, it still catches 90% of bugs that tend to be introduced during refactoring. And makes writing code way easier, because 90% of the time it gives you enough information about the objects you're dealing with that you know how to operate on them.

And in the example with peer being in LAN range - I'd say you still want to validate that in one place, where the value enters your program, so as to have a single source of truth. And in case that validation ever needs to be changed, there's just one place to do it.

You can even add a marker type that wraps an IP address saying that "this IP address is from LAN", and make it so that the only place allowed to instantiate that type is the LAN validation function. Though in most cases I wouldn't go that far.

Follow

@Wolf480pl

Yes, it is one possible approach. Just by no means the only one nor inherently superior.

Especially since I started having to worry about the bigger picture, e.g. dealing with quality, finance and compliance issues, I have learned to stay away from dogmatic approaches.

E.g., from a personal perspective I intensely dislike Python; but I will use it when that's the best tool for the job under the circumstances (conversely, see above about 😔).

@0 yeah, but a statically typed language gives you more tools IMO. Of course no type system is perfect, and in many cases a particular type system may in a way stand in your way.

And as you say, it all depends on usecase. I for one like Java and Haskell and yet I'm perfectly aware that they'd be a poor choice for many projects.

But I still think that unless you have very disciplined developers, a large project will on average require less maintenance burden if it's in statically typed language.

@Wolf480pl @0 Personally I don't find Java's type system that helpful, Haskell's definitely is!

Sign in to participate in the conversation
La Quadrature du Net - Mastodon - Media Fédéré

The social network of the future: No ads, no corporate surveillance, ethical design, and decentralization! Own your data with Mastodon!