Video není dostupné.
Omlouváme se.
This Is A Game Changer
Vložit
- čas přidán 4. 06. 2024
- Twitch
Everything is built live on twitch
Twitch : bit.ly/3xhFO3E
Discord: discord.gg/ThePrimeagen
Spotify DevHour: open.spotify.c...
Editor
All my videos are edited by Flip. Give him a follow! / flipmediaprod
Join this channel to get access to perks:
/ @theprimeagen
Links
Linode: linode.com/prime
/ discord
Twitch: / theprimeagen
Insta: / theprimeagen
Twitter: / theprimeagen
VimRC & i3: github.com/The...
Keyboard 15% off bit.ly/Prime360 USE CODE PRIME360
#coding #neovim #typescript #programming #vim #softwareengineering #codinglife #webdesign #webdevelopment #webdev #javascript #rustlang #rust #twitch #twitchstreamer #programmerhumor #codinghumor #software #softwareengineer #softwaredeveloper #softwaredevelopment
For those that are confused about this:
this has nothing to do with typing it has to do with INVARIANTS. imagine you have a private function that requires some _state_ of the world to exist. it _MUST NOT BE CALLED EVER_ without that. So if it breaks from its _REQUIREMENT_ crash the program with the state that lead up to this and that way you can fix your program based on the state that lead to the issue
From what I understood maybe a better example would be range constraint on a number instead of requiring it to exist. Something like you crash a program if you try to reduce your bank account balance by negative number.
That was one of my pet peeves with rust ~4 years ago, with it panicking instead of crashing when memory exception occurred.
Since panic was causing the program to exit I spent way too long trying to reproduce the bug inside a debugger, instead of having a coredump I could work with
Is this guard clauses?
so just throw a runtime exception?
@@TheKennyWorld not really, he abort execution.
Although a runtime exception does abort the program when not handled, it can (and should) lead to some recovery.
If a function invariant is not respected, the state of the program could be considered unrecoverable, and crashing the program is the best way to get a meaningful report on why that invariant wasn't respected
After 20 years of being corrupted by JavaScript's nonexistent typing habits, man comes back to the land of the sane.
I just started using typescript files instead of Jsx a few weeks ago and god damn was that frustrating. After a couple of days of slogging through it and it finally clicking. I can honestly say it was definitely worth it just for the readability. Now I’m going to have to apply this new addition to it to prevent more pain in my future. Life is pain, and that’s ok.
Yep. All this would just be fixed if every program language had a proper type system
There are many untyped languages 🤷♀️
@@Frexuz such as?
@@HenryTitor Lua python ruby php
Man discovered asserts
Hahahahahahhahahhahahhaha😄, I was like what the f**k this is elementary programming 😂😂
same, i watched this and like, wtf. maybe he has expiriennce of 4 weeks of programming not 20 years.
I guess this is what happens when you code in an environment that doesn't punish you by crashing in its entirety when a throwing operation occurs. "Hey, this only stung for a bit, so it's probably fine." - Fast-forward to swollen itch 2 dev cycles later.
Came here to say this. Jesus.
Guys he was very senior at Netflix and his courses are pretty good. It's a short don't take it too seriously..
Didn't we call this defensive programming?
i like to work offensively..... i just add bug if there is no bugs in my non tested code... and catch it without throwing a error or printing in console... so no one in the future came to know about it for fixing it..
@@vaisakhkm783silly 🪿
I think it's a subset of defensive programming. The idea he's presenting is to crash the program if inputs are out of expectations with asserts
@@steveaguay I think that it pivots on your position of crashing in regards to defensive programming. An argument could be made that a defensive programming style should strive to eliminate crashes.
It is called offensive programming, because offense is the best defense. (That is a joke, but also why it has this name.)
Technically, it is a subset of defensive programming. Defensive programming normally returns from the function with a best effort or a default result. But that kind of defensive programming is really really really really bad. Because it actively hides bugs and makes them extremely hard to debug.
Offensive programming shows an error to the user, but you'll get bug reports with stack traces that tell you exactly where you need to look for the bug.
As long as your user doesn't die when a stack trace is made, then this is the best possible outcome. If your user does die when a stack trace is made, you could instead return a default value which means the user dies of unknown causes. That could be better for your insurance premium, I guess.
That sounds like strong typing with extra steps
The one difference is this fails at runtime instead of "failure at compile". Which at times might give a bit of desired design flexibility.
@@jks234 i dont really understand the appeal. My #1 priority has always been to have things fail before I run the build so I dont have to hunt down edge cases at runtime.
Regardless of your type system, this can catch things that the type system cannot. I.e. asserting that the length of two lists is equal for example.
@@jks234 What? But if the assertion fails, the program exits. It's the same thing but with static typing, you catch it before profucti and you save lots of time and headache.
@@BosonCollider Yeah, the example wasn't about that however. It's about the fact that the value isn't undefined (meaning it has literal no value, meaning, it's a null pointer).
Negative space what? You just validated input my dude
The negative space is between his ears.
@@pistachio8859lmao
Right! haha it is so fucking dumb its almost unbelievable.
Haha. Exactly. Well works for shorts and likes who's ee it first time 😂
I'm actually baffled if he truly spent 20 years as a developer without asserting program states. Guys, cover your fail scenarios when writing code, even if just by throwing an exception. You can go back later and expand on it, but you'll waste a LOT of time trying to find failure points in a complete code. Do the devil's work first.
What I don’t understand is how you were programming without this mindset.
There are so many scripting languages with loose typedefs. There are literally drag/drop graphical programming languages now. Their statements they don't even need try/catch or even catch-alls. Assert is closer to state-based error checking but it's better than nothing.
Javascript brainrot. Source: I have Javascript brainrot.
I figured this out well under a year after starting to code.
Unit tests anyone?…
I guarantee you that 80 percent of developers hear about it the first time. The fact that you know it, doesn’t mean anything.
It’s called assertive programming.
There is an odd irony here about high-level programmers learning that type ambiguity is not always a good thing which is incredibly funny to me.
Because they usually rave on about the opposite.
Type ambiguity is a great power that comes with even greater responsibility
There are also programmers that promote designing concrete architecture for everything, and then discover that simple interfaces make a lot of problems easier. Someone might find a funny irony to that as well.
The thing is both types could learn a lot from each other, but a lot of people get entrenched in their corner of experience.
@@SoupOrNothing I hate having responsibility though
Type ambiguity is NEVER a good thing.
Don't even get me started about the faux-duck typing
@@SoupOrNothing it is just laziness wrapped in excuses
Javascript developers try not to completely fuck everything up challenge: impossible
20 years?? Just imagine what else this guy hasnt figured out yet
This is brutal.
😂😂😂😂
I love his content in general. I'm also 20 years in, and that makes me wonder what super obvious basic practice I missed along the way. I'm sure we all need to practice the basics, and turning my gaze at myself, it makes me want to self study.
having said that yes, discovering the "functional/assert" vs "data type" strategy tradeoff 20 years in would be considered professionally embarrassing. If this was me, I might silently delete the video.
For those other so-called software engineers who haven't gotten a clue in 20 years, i recommend reading up on "design by contract" by Betrand Meyer. Also I wish more people would read up on Josh Bloch's book on Effective Java even if you don't program in Java.
But you knew it. You are so great, you are making this world so much better place. You know everything, how is that possible… you are my idol and to everyone in this world. You are so awesome and amazing. You are the smartest person we know. Thank you for your existence. 🙏
dude has a degree in yapping
Masters of Arts in yappin
@@ThePrimeagen yappin is not just a city in China
You can also start to use type which would enforce the invariant in their constructor instead of making the same assertion in multiple places.
And be referentially transparent
And convert a runtime error into an edit time error, so you didn't have to waste time compiling your code before you got started fixing it.
He used a poor example. It's about making sure the state of the program at runtime matches the assumptions that were made when writing that code. You can't check that with the type system of any mainstream language, and if an assumption like that is not correct it's a bug so you really want it to crash at that point.
And while in theory it's possible to avoid such bugs with dependent types that only covers the code you write and not its environment.
why the fuck am i here, ive never touched a line of code in my life
Hello world
One doesn’t touch a line of code one writes a line of code
@@Zeroduckies😂😂😂😂
@@ahmedjaad4940 nah, I've removed lines of code on projects. I'm told senior devs lines of code tend to measure in negative numbers.
I think the algorithm has chosen you.
In university we called this design by contract. You just assert your pre/post conditions and your invariants.
Parse, don't validate. Value objects can be used to enforce contracts in compilation time. Once a value object is created, it remains valid.
this is also called "defensive programming"
This is called design by contract and was perfected by the Eiffel language. So sad that greed and short vision killed this language.
@@llothar68 but in design by contract some/most/all of the contracts are verified at compile time right? While defensive programming focuses on run-time checks.
Design by contract is awesome. One of those great ideas that will keep coming back.
@@rodrigob No, design by Contract in Eiffel does it at runtime. It's not Rust, Rust sucks. Eiffel rocks (rocked).
Nah, this is called programming
@@llothar68 The problem is that about 20 years ago, web development was all the rage, and webdevs didn't want to deal with things like strict typing, exception handling, or runtime crashes, so they made and used languages like PHP and Javascript, that will try to keep running even if the world ends.
They're finally learning why it's nice to have a compiler yell at you when you try to stuff a string into an integer value.
So... you added validation cases?
Is it 'negative space programming' or just a fundamental concept of robustness?
Validation would not be wrapped by assertions that are only valid in debug mode
Me as a java programmer: 👀👄👀
Typical Java programmer with 4 eyes 😂
@@thehibbiabout to point that out as well😂😂
Java has assertions
@@KemikalsAren't Java assertions just non checked exceptions? And then you could accidentally catch an assertion if you use catch(Exception e)? I might be misremembering
@@nbecnbec It's not quite an Exception so your catch statement would not catch it. But there are ways to catch it nonetheless. Even disable all assertion statements globally via an option.
Bro discovered guard clauses and made them worse by crashing the whole program. Nice.
I think the program should definitely crash and not let a broken program continue to run because something that should never happen, happened.
@@nevz9851 If you're deep in the call stack and hit an invalid state, who are you to decide if it’s recoverable or not? Truly unrecoverable states are really, really rare. Your job is to notify the parent function and let it try to recover. You keep bubbling up until either the state is fixed or you hit the main function. Only in that exeptionally rare case should you even consider crashing
It breaks in the debugger, sorta the point
@@nevz9851 Open your browser and browse the web on YT or other sites for a little.
Every red console error is the webpage crashing. No thanks.
@@nevz9851It should not crash, it should throw an actual meaningful exception that will be caught later and some mechanism should try to recover or compensate it
This is in many text books. I'm so confused about it being game changing.
You (and I) learned systems programming. He learned web programming. We learned on languages that do this by default, he learned on languages where you don't even have to declare a variable before reading from it.
@@ClokworkGremlin Err ... what? He has a CS degree; he would have learned the same things you guys learned.
@@ClokworkGremlin This is why I hate dynamic languages and do whatever I can to stay with static typed languages. So SOOOO hard to read years of random developers writing JS code as the JS itself changes.. more frameworks, more additions to language.. its a fucking mess of a language.
guys, this is not about typing or asserts. Defining the negative space of your program means that not only you define what it should do - but also declare what it shouldn't.
I dont see the difference/advantage of this over just checking bar isn't falsey
With a statically typed language there isn't any "should" or "should not" only what you intentionally allowed it to do.
My function can never pass me the wrong type because it's literally impossible.
And what happens after the check? Just checking doesn't do anything
You can see this as such a statement "this only works with numbers", if type definition will change, it will crash.
@@NihongoWakannai it’s not about types. If your function does not allow your int value to be zero, how would you solve this just with static types?
@@epaniyYoutub so what, just throwing an error when your function gets an invalid value is a "game changer"? I thought that was a common sense pattern.
Isn’t it called statically typed programming?
No i think you are missing something. He ment not using general errors and not propagating them, instead use asserts in code which crashes the program when something unexpected happens
Static typing can prevent errors, yes. But, no static type system is expressive enough to capture every possible assert that you might need.
Sometimes, the assert is less effort than designing a type system that fully blocks all possible bad scenarios, even when it's technically possible to use the type system by itself.
@@cyberflaw_ But it's clearly not unexpected, because we've typed it as potentially undefined.
Yep, it should actually crash, cause smth is uo! So many "bugs" cause actual harm like paypals shopping cart item spoof, and getting money refunded that was never paid etc its better to just crash and nope out of there.
Although not sure if he writes a cli using node? if its an online service discord bot etc. it should only crash that particulars requests subroutine and log it, instead of taking the service down.
Since javascript is shit, we DO need to use error, try-catch the entire run and handle error, or an error handler that checks stderr, then you actuall can just have the function crash@@cyberflaw_
Nope, he attempted to explain something more general. Example, when you implement a divide function, you can assert divisor!=0.
Since you’re using typescript, why not enforce a strong type and actually provide the number?
because Foo might need to have optional `bar`, the whole application probably will have more logic than one function.
But if in this function it's required to have object with property number - then it makes sense to do this assert
Is this just a "bad" example or is there some real world case where you would rather do this than evaluate the value when you get it and define your functions so that they take known types?
Here's a better example. I wanted a method (IsMemberOf) to check if a customer is a member of an organization, and return false if they're not.
However, for performance reasons, the members field on the organization might not have been populated, yet.
Without an assert, the code blindly returns false for all customers whenever the members property is missing, because of the way it does the check. But false is not the right result. Neither is true, because we don't know if the customer is a member or not.
Instead, we need to assert that the members field has been properly loaded; it's not valid to even ask IsMemberOf? until we fully build out the organization object.
Adding the assert changes a subtle bug (my organization members aren't recognized, but only in some code paths, somewhere I can't figure out) into an obvious one (my new code causes a failed assert the first time I test it).
@@creativecraving wouldn`t it be better to use a different type than? which doesn`t allow isMemberOf to be optional?
@@dotnetappthat would be essentially the same thing. You would still have to cast the parameters into said type and throw an error if it is undefined. Of course you can try fit the original data to always be defined but the constraint here for allowing undefined is performance (as stated by the original commenter)
@@dotnetapp Possibility, especially if you're using a language that gives you access to types. But, that falls down a little bit if you've got multiple "performance-optimized" members of a type, and you might have any combination of them unavailable at the time you're writing code.
You could argue that's a bad API that needs to change; but, you also may not have the resources to change it, either.
I love how JavaScript makes this an issue
Part of the reason I like Rust so much is because when you combine general functional practices with its typing system, it forces you to become aware of almost all of the subconcious assertions you make and explicitly handle them, usually in the form of a `Some` or `Result` enum. You can call `Unwrap()` to ignore them if you want but you have to counciously do it
Yeah I could say the same thing as this guy: I changed my programming style after 20 years. But it wasn’t because I was clever, it’s because I started using a language made by clever people for grug brains like me.
Rust has assert as well. What he means isn't covered by the type system but his example is bad because it made it seem that way.
@SaHaRaSquad In my personal opinion, assertions like this *should* be covered in the type system for a well-architected solution. I understand that his example here is arbitrary. At the end of the day, all a type is is a set of all of its invariants which it can polymorphically be, made up of the sum of all enums and the product of all fields (at least in Rust). All of the invariants should, ideally, be considered valid inputs for a function. I.e., if you have a function which needs a cardinal direction (i.e. North, East, South, West), one option would be to use strings of "North", "East", etc... to represent this input. However, strings can represent WAY more than just the 4 states needed ("a", "aa", "aaa", ...), so you'll end up needing to assert in the function if the string represents one of the 4 proper states at runtime. Instead, we can put that work on the compiler by having an enum that represents EXACTLY our 4 valid states, thereby moving the check from the function's responsibility. It is just straight up impossible to give the function something invalid. I think the type system has *everything* to do with enforcing invariant validity.
@@grantpeterson2524 Again, even the type system in Rust cannot represent everything. You need dependent types for that and very few niche languages support that.
@SaHaRaSquad I want to make sure I understand what you're saying so I can internalize it, but I don't think I totally get it. Can you explain an example of something not enforceable by the type system? The raw backing data behind a struct's type may not be a perfect 1:1 representation of all your variants, but by limiting the ability to construct your structs directly you can make it so that invalid variants are rejected. I.e., const generics allow you to define a type of "BoundedInteger", where Lower and Upper are integer literals that are a part of the type. Then, the constructor for this type could return an Option, returning None if a value isn't in a range. Thereby, providing guarantees about the value contained in the type. This isn't full dependent types, but it's comparable in terms of practical usability for development in my experience.
Is this guy like the thor version of programming? Telling the most obvious shit while looking smart. I'm missing a paint drawing to go with it.
Negative space programming? What?
This has been standard practice in every programming shop I've been in for the past 25 years.
It has different names in different environments. Pre/-Postconditions. Defensive programming. Protocolls. Assertive programming. Never heard anyone call it "negative space programming" (ridiculous name IMHO).
Oh. And having to type check the input type is you fixing a flaw in that unsafe script kiddy language.
I think I saw it for the fist time in MS' MFC framework from 1999.
its actually pretty popular term and its used with Tiger Beetle / Tiger Style
ratfactor.com/cards/tiger-style
@@ThePrimeagen
Thanks! I couldn't make sense of the name. Not sure if that should worry me. I get it now, but I'd still say it's too clever for it's own good. The alternatives are all more straight forward (KISS).
You demonstrated pre-conditions. There are also post-conditions, where you assert on assumptions made at the end of a function.
I remember a Microsoft guy back in the early 90s tearing his hair out while retroactively introducing pre-condition assertions to an existing Windows DLL (can't remember which one), and discovering hundreds of people throughout MS had been using the DLL incorrectly. Everybody hated the DLL. Everybody hated him for forcing them to fix things they (incorrectly) believed had worked. Eventually things stabilized, but only after he aged 5 years in six months. Moral of the story:
If your code will be used by other developers, assert the F out of the public interface and do it early, before wide release.
It's also called LBYL in Python world - look before you leap (precondition checking). And is contrasted with EAFP (or exception based approach). It's crazy that PrimeTime does't know this.
@@mindasb
Yeah. I haven't heard that before either, but "look before you leap" already yells "pre-condition checks" to me.
Maybe people who are purely front-end developers wouldn't automatically stumble across assertions? Assertions are useless for things that need to fail gracefully, like user input validation checking done at higher levels of the software stack. At lower levels you're defending primarily against programming logic errors, so you get more utility out of assertions there. That's the only thing I can think of.
Some sort of assertion facility is is included in the library of every major language, and assertions have been around since before unit testing was a thing.
I didn’t even know this had a name. I thought this was just what you do. Because duh.
Wouldn't it be "bar must exist" instead of foo?
Except assert from "node:console" just logs and doesn't throw when the invariant doesn't hold 🙈 You need the assert from "node:assert" instead.
My jam when coding is a bunch of prints through the code within a try/catch. I love how it allows me to code a full section by intuition and the program doesn't ever 'break',and then the debugging goes swiftly as I analyse the prints through the code logic flow.
I see it as a Tetris game you lose right at the start after the pieces fill the board, but you can go back and sort your pieces to get the winning formula.
AKA "design by contract".
This is not a good example because most people are focusing on null, strong typing, etc when it's really about enforcing a contract on valid parameter state. Strongly typed languages have these problems, too, but the surface area to cover might not be as large as a dynamic language's.
True, but it's just a terrible example because he's using Typescript here, and there's a much better way to handle this sort of problem in TS. So if you have experience with TS seeing this video makes you cringe a bit.
It would have been better if he just stuck to vanilla JS for the example.
Im annoyed that he didnt assert is was a number but rather than undefined. Like what happens if it gets passed a string?
Typescript will complain if so
@@viktorwestberg2290 it will just throw compile time errors. Won't be a problem at runtime.
I believe the type definition states it can either be a number or undefined, it can’t be assigned any other value.
Man discovered guard clauses (edit: The distinction on crashing the program is important)
Telling a dev who worked at Netflix for a decade that he discovered guard clauses lmao. Just cause u don't understand what he is talking about doesn't mean you have to speak your own ignorance
@@mhqa_dude, he just yapped and said big words to describe a guard clause.
no, a guard clause just lets a function exit early. These "design by contract" assertions are intended to intentionally cause the program to crash if the internal state of the system is not what the programmer expected it to be.
@@RayBellis Instead of crashing the whole program you should properly handle edge cases which you did not expect
@@sinan720 and you've just missed the entire point of the video
This may be the best comment section I've ever seen.
Finally, some jackass "guru" is spewing nonesense and everyone is calling him out on it.
I'm proud of you guys :)
Love it 😂
that's....... that's what asserts are for
he discovered asserts
Isn't it enough to do a (typeof x === "number") check? Why would anyone use assert for basic checks?
he just discovered it, same reason why little kids talk about their feces
I called it Paranoïa programming. Every function or method has state validation to rule. Other words the function or method acts like it is in a no-trust environment. This saved me more than once.
Rust: “look what they need to mimic a fraction of our power”
You are doing a simplified/modified form of design by contract. It is a concept invented almost 40 years ago by Bertrand Meyer creator of the Eiffel lang.
Wouldn't you update the parameter to only except a non nullable number? Then when you use the "morphFoo" method, the contract only accepts non nullable numbers therefore it would always be valid
Totally agree. Here you have to look at the function body to see that undefined is not allowed
Yeah this is the smart Typescript way to do it. You have types, so only accept a type that's a valid state.
This video seems like a JS programmer that isn't familiar with what TS can do. He's checking the type of the data instead of letting the type-checker do that for him.
Except that oops… someone decided to update the REST endpoint you are relying on, didn’t tell you and now you are seeing that it’s trying to insert an NULL value in the database. You don’t know from where.
@@taragnor TS won't guarantee types at runtime, obviously, so his point is to crash the program when the statically expected type (your TS type) differs from what actually was received at runtime
have done this for 20 years myself.... Simply because I never trust anything, never assume inputs. And my codes have to be a perfection, like the borg.
Wait, how's this different from contract programming? Is it just the lack of contracts as a language feature like D or Ada have it so you have to use manual exception/error raising guard clauses?
This ethos was right there in the onboarding document at my first job. The architect who wrote it gave one motto - "millions of assertions".
They would just straight up reboot the machine if any assertion failed. Gave them legit more than 99% uptime.
yeah crashing programs in production is super useful
Asserts don't crash in production, this is for testing and debugging. In fact some compilers can use them as hints for better optimizations in release builds.
It would crash anyways.
Dude every time I see some asshole say "typing (x) is a waste of time, any dev worth your time should know how (x) works" I lose a little more faith in what i can expect from other seniors, so this is majestic and I love it.
Genius!! We should call it 'type-safety' and maybe create things that enforce them before the program is even run... we could call them 'compilers', they could just transform the code directly into machine code that respects the declared types!! We gotta patent this!!
Dude, seriously? If you're deep in the call stack and hit an invalid state, who are you to decide if it’s recoverable or not? Truly unrecoverable states are really, really rare. Your job is to notify the parent function and let it try to recover. You keep bubbling up until either the state is fixed or you hit the main function. Only in that exeptionally rare case should you even consider crashing.
Dumb question but can't you just catch an assertion exception in the parent function? It seems like your opinion (that I agree with) is not mutually exclusive with Prime's assert guard clause.
@@smithastley1616 I am pretty sure it was part of Prime's argument that the program should crash, which i strongly disagree with
You are correct, in some languages assert throws an exception, but this exception is not meant to be caught as it is not strongly typed and for example in java its a unchecked exception, which means the parent function has no knowledge of it at compile time and wont be able to handle it. Also, some languages (rust, go, c++) staight up CRASH without any exception if an assert fails.
Guard clauses should have typed and checked exceptions (or result monads in case of rust) and asserts are just the wrong tool for the job
@@sinan720 Node.js doesn't crash on assert though. Forcing a crash is an extremely rare antipattern in JavaScript, I've yet to encounter a library which defaults to that (or one that even optionally supports it for that matter). It will throw an error, which will only cause a "crash" if it bubbles all the way to the top. I know he says the word "crash", but the code speaks for itself.
I often use a guard pattern - at the beginning of an important function I check all (well, at least 90% because there's always 10% of Murphy's law) my assumptions about the parameters and the state of the "outside world" and I assert or throw argument exceptions. When finally I'm somewhat sure that it's safe to proceed, I implement the remaining code.
The real question is why are you shipping production code with asserts in it.
Foo bar is the worst convention ever and programmers need to change it.
This reminds me of how we used to always check for null before non-nullable types was a thing in c#.
all of the boilerplate of a type system with all the extra guard checks of a dynamic language. TS really is beautiful.
If it took you 20 years to figure that out, I don't even want to imagine the kind of code you wrote 20 years ago.
Design by contract basically
DbC means the static structure protects you. The contract is explicit at build time. This is run time checking. Not the same.
I use guard pattern - at the beginning of an important function I check all (well, at least 90% because there's always 10% of Murphy's law) my assumptions about the parameters and the state of the "outside world" and I assert or throw argument exceptions. When finally I'm somewhat sure that it's safe to proceed, I implement the remaining code.
I love your discovery! Welcome. I also want to add say that this is generally seen as best practice when using weak memory stores in functions. Basically, without assets, weak vars are just a nightmare, however with, weak typing is more flexible and powerful than types. If the top of a function isn't a list of asserts, I stop people and teach them straight away. In languages that don't have asserts, I always role a nice assert library for use.
This is one of the reasons I prefer weak types, because you can be PRECISE on a FUNCTIONAL level about what EXACTLY is invariant about all or part of the data type -- vs trying to over engineer types and carry extreme assumptions all over an enterprise application.
I even made a library for standardizing asserts, (almost like types) so they can be partially applied across portions of JSON and reused -- kind something less hardcore than types, allows for easy casting, and is magical on data streams and message libraries.
Typescript should show that as error or at least a warning.
Not really, typescript can't assert everything and there are cases in which even if you think that you have 100% type safety, you might end up with something being undefined, that is typed as always defined
@@xromasik This doesn't compile in TS. It's a bad example on his part. When typescript is used correctly (i.e. strict mode where all the system inputs are parsed through a validator like zod/ajv), there is no need for this level of defensive programming in one's application code.
@@pokalen
function someApiThatReturnsAnUndefinedValueButItShouldReallyBeAString() : string
{ return undefined!; }
const value: string = someApi…();
There. TS is super happy about that code.
That is dumb. Just define the interface correctly or if optional use defaults. The option bar makes no sense in this example
The is better
exactly, using type level assertations only makes sense when static checking isn't an option like getting external input
that's why moving from JS to Dart was the best thing that happened to my programming career
Great approach to always make sure you understand the program does exactly what you think it does. I've been using asserts for ever. They ease your mind.
Important Note: They make debuggin MUCH MUCH slower.
Why does it make debugging slower?
I'm gonna act like I understood all that and what this does and continue scrolling thinking I'm smart now.
good approach to life
Js "people" smh
😂😂
obviously no clue who he is
Man I wish I started programming 20 years ago. Too bad I was 4 years old. Now I can’t get a job and this guy just learned about asserts.
My lead taught me this, really helpful with handling errors in event queues, message passing, even http responses. Really good stuff
He just had his JavaScript moment.
And as a profound JS dev, he had to name already name stuff the worst name possible.
It's statically typed programming with Runtime type validation
If the validation is at runtime, then by definition, it isn't static. That's the opposite of static.
@@creativecraving😂 🤦🏽♂️
I was taught to assert expectations 25 years ago. I haven't done that professionally, in part due to languages i use. I want it.
In C# source code such checks are pretty popular. Even today I wrote some code like this wile working on an old project.
Good to mention that actual Assert functions outside of unit tests are not very popular in C# these days, but just throwing exceptions, like an InvalidOperationException or even UnreachableException.
And I even think that's one of the most valid use cases of exceptions in modern code. Because in my opinion exception throwing should be used the same way as panic in Rust or Go, namely to denote an actual bug in your program, and not a an something like an input, output or user error.
This is what an expressive type system is for: being able to express more than just Integer or String, but actual invariants. That's why dependent types are so interesting: they extend vastly the class of invariants you can express.
wait until you discover C# (runs in any browser now) and the compiler will gurantees that a variable has the type you expect. and if is FAST. and even better you can simply change the type you expect and the compiler will tell you what you need to do to adjust the rest of your code
I love nullable in C#. It can be a biotch because you are forced to make good code. Ok in this case you need look why foo can be null, if possible work your way up the code to prevent it ever being null. In C# you can use decorators to remove the nullable once you've handled the situation. TryParse functions can also help in some situations. I love these strict programming languages.😊❤
Would it work to change the type signature to take a NamedFoo instead, which augments Foo so that name is required?
It seems like the issue is that you want to only ever call morphFoo when Foo.name exists, so you can tell the type checker that in advance?
I would love to see a more in-depth discussion of this. I see the value in failing early. However, when would one use assert, when would one throw an exception instead? Also, should the asserts be kept in production?
I did something similar when I was building a game for my thesis, state got so difficult to manage (cuz who needs a proper state machine lets just raw dog it, stupid me thought) that I just had to start calling like 30 lines of asserts on every frame just for me to immediately know if anything is off. I went through too many several hour long debug sessions only to find it started with a simple mistake that escalated to an apocalypse 5 frames later...
i’m new to assert. never used it. Why not just use a try catch block? what’s the difference?
I exactly did this in my js/ts programs but my (junior) colleagues couldnt understand why I did this because they were so sure that the value had to exist
This is pretty slick, I kind of like this better than the typical throw some error approach. I'll give it a go with tools I need to build soon
This approach will breakdown in a more complex case where you have complex data with rather large set of possible cases that constitute "wrong" state
That is not negative space programing, that is some kind of "strong type" implementation
Its a bit like „exit early“. is also a good way to structure logic in a func
Could we not move this check to the type the function requires? You cannot have a value of this type that does not meet the requirements of our function. To me, a function definition says; "I do this if given this type." If you then suddenly crash, that function lied to me and needs to limit it's accepted input. Limit the number of places where you cannot trust your input and encode that safety in the typesystem. If I get an Age type as input, I know that it is between 0-130. I don't have to crash or even check if it's negative because Age, by definition, isn't.
Bertrand Meyer popularized this idea back in the 90s with the Eiffel programming language. He didn’t call in negative space programming, just programming. Today modern languages like rust can add compile time guarantees to these sorts of assertions
bro just invented preconditions... I learnt this from day 1 mate
Thank you for showing me this amazing practice I will immediately add to my personal list of horrible practices.
When I landed my first job, I learned something : never make your program crash. If something goes wrong, it should not crash, it should always handle the problem graciously. Even if it means silently fail, or do nothing and let the puzzled user wondering why things don't work. The program should never crash. In engineering school, if the program crashes because of an invalid input, you got a zero mark. Never make your program crash.
negative space programming, basically writing an input validation that can handle most negative cases without having myselft to wrote a whole paragraph of code.
I heard some 20 years experience Microsoft guy (he has a CZcams channel as well) talking about similar thing. He terms it as programming with intent. You know exactly what data type and data object schema you want in functions and you build the program using that intent. If it fails, either your program has a bug due to missing error handling or you miscalculated requirements.
There's often a better option, such as skipping logic that depends on the invariant and logging important info. Too often "invariants" turn out to be "incorrect assumptions", especially in large/legacy projects. You're more likely to be able to wait until morning to deal with a bunch of log messages than an API returning server errors, and it's probably less disruptive for consumers in the meantime.
And when you think we can't sink any lower you find this guy with a shovel and confidence.
YES. I'm more of an analyst / scientist when it comes to data than a programmer but whenever anything pipeline related is thrown my way I am VERY strict with its parameters.
While upfront it might make me work longer hours to validate, update and fix the literal days of my life it's saved me over time is appreciable. Either I misunderstood the business around me or there's something going wrong with the pipeline I need to deal with.
did you pick this from the TigerBeetle world? i've been thinking about going all-in with asserts in python.
Me writing 5 codes of lines in programming outside c++ in my entire life( it was python): hmm... interesting
Asserts with high level Try-Catch are a great mix. Let's say your function should never receive a value leas than 1. Just assert this invariant as the first line in your method and let the higher level try-catch catch the error. Saves you from undefined behavior.
I think what prime is trying to explain here is making sure the state of the program and all inputs are valid at all times. Not just NULL checks, but also if a value is in a certain expected range.
This problem is also addressed in the Ada type system. Though i dont have much experience with it at the moment, so correct me if im wrong
just require bar to be defined in morphFoo' input and assert outside; the example is lacking
it doesn't show invariants, it shows typing issue instead
(now, if the requirement was "bar has to be >= 5" that's much closer to what you want to show)
Discovering this just now is insane... this is the only way to do type safety in vanilla Js...
Ideally, solve these problems at the type level. Parse and fail as early as possible.
In this example, assuming "number?" is necessary, that means converting from "number?" to "number" (or from Foo to BetterFoo) as soon as we know bar cannot be undefined.
But in cases where this is too inconvenient, an assert might also be fine :)
You know what you'd like? A statically typed programming language
instead of a bunch of handling of potential faults in the state of the system, insist that the state of the system is perfectly suited for the function. If you make every function insist on a perfect system to operate in, they will either all perfectly operate or it will completely crash.
This is especially useful later on when the bug appears. You'll know exactly what's wrong and can go immediately work on fixing it, instead of spending hours trying to figure out what's wrong in the first place.
If I’m not wrong, when you use guards in swift you basically subscribe to this paradise right?
When you think it’s going to be another Thor video then you see Serj Tankian explaining god knows what out of nowhere.
(Edit because auto corrected serj to Seth)