News for hackers. Stuff that matters.
Re:Parse, Don’t Validate by Izkata on Thursday November 07, 2019 @04:41PM (#21477603)
This is describing what I've known as "Typed Hungarian notation", and have seen a few times before, though I can't seem to find now.

The original intent of Hungarian notation was to encode metadata into the variable name - for example, "validData = validate(rawData); showValidData(validData)". The idea was that the prefixes would make it just look wrong to the programmer if someone accidentally used mismatched names, such as "showValidData(rawData)", indicating a likely bug.

This notation mutated into the far more simplistic and arguably less useful "prefix with the datatype", such as iFoo indicating Foo is an integer. This mutation became known as Systems Hungarian, while the original became Apps Hungarian.

The suggestion in this post is taking Apps Hungarian, and instead of relying on variable names, encoding it into the type system itself.

The first time I recall seeing something like this suggested was actually in Java, with examples in that blog post involving class attributes:

  public String Name;
  public String Address;
And creating classes to represent these values, preventing them from being used the wrong way:

  public NameType Name;
  public AddressType Address;
...which is why I remember this as "Typed Hungarian" - making the language's type system handle the work that a person would normally have to think about in Apps Hungarian.
Re:Parse, Don’t Validate by radicalbyte on Thursday November 07, 2019 @05:32PM (#21478007)
The Java example you've provided is known as Domain Modeling, it's well described (and honestly greatly expanded on) in Domain Driven Design by Eric Evans.

It's applied heavily in the enterprise world simply because it's so powerful. In general as the domain logic becomes more complex the benefits of doing this increase.

Actually, not encountering this style in code-base which is solving a complex problem is a massive warning sign for me. It usually means that concepts are poorly defined and that the logic is scattered randomly all over the code-base.

Apps Hungarian is just a logical style: name functions, variables, types so that they're meaningful within your domain. The result of which is code which is very easy to understand for someone who understands the domain. This doesn't mean long names - if you're doing anything math intensive then using the short names which conform to the norms of the field is perfect. For a business process it probably isn't :)

Re:Parse, Don’t Validate by gambler on Friday November 08, 2019 @02:20AM (#21480500)
>Actually, not encountering this style in code-base which is solving a complex problem is a massive warning sign for me.

There is a fine line between capturing some common meaning in a reusable type (e.g. Optional<T>) and spending most of your time crafting a straight-jacket of type restrictions that are supposed to thwart some imaginary low-level bug in the future.

Java is actually a great example of how this mentality backfires in real life. The language, from day 1, had a zillion ways to force someone else to do something they didn't want to. Abstract classes. Private methods. Final classes. Etc. It was supposed to ensure good design, but in practice just led to the endless reenactment of the banana-gorilla-jungle problem. (https://pastebin.com/uvr99kBE)

At the same time, the language designers didn't add such basic features as lambdas and streams until 1.8. This lead to creation of ungodly amount of easily preventable bugs, since everyone was writing those awful imperative loops.

Re:Parse, Don’t Validate by monoideism on Friday November 08, 2019 @06:56AM (#21481471)
Banana-gorilla-jungle problem results from OOP. This article (and presumably, the GP) is describing encoding domain-driven logic in a statically-typed functional language, and thus the OOP issues are not a problem.

Functional languages don't carry around their environment with them, so you just get a banana. No gorilla or jungle.

Re:Parse, Don’t Validate by marcosdumay on Friday November 08, 2019 @07:38AM (#21481680)
Oh, it does have some banana-gorilla-jungle problem, it's just not at the same place.

If the types are computationally equivalent, there is a plentora of type classes you must inherit, there is a lot of packing and unpacking to make them work with standard libraries (how do you print an address?), and if the values are not completely separable, there are plenty of conversion issues.

It is an improvement, no doubt about it, but the main benefit of the languages with advanced type systems is that you can refactor code easily to add them only to the places where it's a win, only after your code is complex enough to make it a win.

Re:Parse, Don’t Validate by gambler on Friday November 08, 2019 @12:38PM (#21484632)
>Banana-gorilla-jungle problem results from OOP.

Not really. There are specific design decisions that Java made which enabled this issue to manifest. I've recently took a foray into Smalltalk and it doesn't have this problem, because methods depend on object interfaces rather than class types. AFAIK, OCaml also got this issue right while keeping static type checks - they decoupled classes from types.

>Functional languages don't carry around their environment with them

It is entirely possible to recreate the issue in a functional language, as long as there are sufficiently powerful mechanisms to enforce type safety during compilation. In fact, if you don't understand this and follow the advice in the article too far, that's exactly where you will end up. You will have a jungle monad containing gorilla monad holding hostage the banana data structure the user actually cares about.

Re:Parse, Don’t Validate by monoideism on Monday November 18, 2019 @01:05AM (#21562253)
In the off chance you're reading this 9 days later, I'd like to push back against this response (working on an OCaml project at work, actually).

> AFAIK, OCaml also got this issue right while keeping static type checks - they decoupled classes from types.

If you mean that the types correspond with OCaml classes themselves and not the objects that classes create, yes, that's correct. But it sounds like you might mean the opposite of that. In any case, people rarely use the O part of OCaml much. Most people find they prefer the first-class modules for almost everything that needs greater modularity than what functions provide. I've found that the only thing that OCaml object system is good for is modeling/wrapping existing OOP or prototypal APIs, like certain XML ones, or some web APIs.

>You will have a jungle monad containing gorilla monad holding hostage the banana data structure the user actually cares about.

While it's true that monads are a way to make normally explicit environments implicit, monads aren't really what the book I'm talking about is about, nor this article.

Yes, monad-heavy code could (with effort) end up with an application monad displaying problems similar to the banana-gorilla-jungle problem. I've frankly never seen monadic code like that, but perhaps you have.

Instead, what this article is advocating for is simply modeling your data correctly. Really, this is a universal programming theme, that helps a lot regardless of programming language. But the structures available in statically-typed functional languages are more powerful and able to model domains with greater granularity. If you're familiar with the saying "make invalid states unrepresentable", then you understand what I mean.

Re:Parse, Don’t Validate by radicalbyte on Friday November 08, 2019 @04:51AM (#21481008)
Java has just had a terrible steward in Oracle. Plus the community seems to like boilerplate code (see: Angular for more of that if you're into javascript).

I switched to C# as my main language specifically because they were gaining awesome features like generics, lambda, LINQ. Since then it just got better and better.

In the C# world you seem to encounter systems where the logic is either in:

* UI event handlers * Methods on helper classes which consume a model generated from a database. * Domain modeled with classes with the logic split between the classes themselves and services which consume classes.

In the first two cases the code tends to have a massive sprawling dependency tree which makes it harder to maintain. In the latter case you've usually got a better chance of having properly isolated code. Even if the isolation isn't super you at least have the logic well organised.

Re:Parse, Don’t Validate by LoSboccacc on Friday November 08, 2019 @02:50AM (#21480599)
it's extremely useful especially at interface level but also in day to day coding, pity the people whose method signature is (string, string, string) because no ide can save them from the churn.
Re:Parse, Don’t Validate by radicalbyte on Thursday November 07, 2019 @05:36PM (#21478036)
It's particularly powerful if you can great an algebra of your domain. You can define invariants which are then enforced by the type system.

I use this a lot when writing C# code and the whole experience is getting better with every new release. Microsoft keep adding awesome stuff like ADTs which make working with these types a dream.

Re:Parse, Don’t Validate by james_s_tayler on Thursday November 07, 2019 @11:45PM (#21480027)
Do you have any resources you can recommend which describe how to create an algebra of a domain?
Re:Parse, Don’t Validate by jen20 on Friday November 08, 2019 @01:32AM (#21480371)
I’d recommend Scott Wlaschin’s excellent book “Domain Modelling made Functional”. The examples are in F# but the concepts apply much more broadly.
Re:Parse, Don’t Validate by kuroguro on Friday November 08, 2019 @07:17AM (#21481563)
Re:Parse, Don’t Validate by q-base on Friday November 08, 2019 @11:49AM (#21484015)
Thanks a lot for that video. Watched the whole thing on the spot. He is actually quite a good presenter and really gets the points across.
Re:Parse, Don’t Validate by smush on Friday November 08, 2019 @11:29AM (#21483765)
Came here to post this. I second this book heartily. If you design your types to be DD with raw, valid, invalid data then by the time you actually get to the database or API, you are sure that your code has passed through however many compile-time enforced validity checks (if you use F# or similar static strong type PL) before it got to this point.

That way, you don't need nearly as much defensive coding re: null checks etc. because the data has gone from 'some client typed some value in an input box, hope its valid' to 'this is an Address line that has been confirmed to be valid structure to pass to downstream systems'.

Pit of success is so much better than peak of success, and much easier to get in a static typed functional language vs. an OO language in my experience.

Re:Parse, Don’t Validate by goostavos on Friday November 08, 2019 @01:48AM (#21480416)
+1 for that book. It totally changed how I thought about types and their role in programming.
Re:Parse, Don’t Validate by monoideism on Friday November 08, 2019 @07:02AM (#21481499)
Agreed. This is a great book. It's changed the way I use statically-typed functional languages.

This article is very much in the same vein.

Re:Parse, Don’t Validate by tigershark on Friday November 08, 2019 @02:04AM (#21480454)
The best thing is that he writes F# in a way that is perfectly understandable by the domain experts so he can use the code as the ubiquitous language. In this way an intermediate representation to communicate with the users is not needed and there is nothing that needs to be kept in sync with the code.
Re:Parse, Don’t Validate by james_s_tayler on Friday November 08, 2019 @03:27AM (#21480697)
Thanks!
Re:Parse, Don’t Validate by smt88 on Friday November 08, 2019 @01:55AM (#21480429)
> Actually, not encountering this style in code-base which is solving a complex problem is a massive warning sign for me.

This is very narrow-minded. DDD as a broad concept is good and something I practice.

DDD in enterprise is a disastrous nightmare. When people on your team are wasting time Googling lingo to try to figure out what kind of object they need, where to put a file, or where a method should go, it's a huge red flag.

I was on a team that seemingly spent all its time trying to figure out what the hell DDD was prescribing, let alone trying to figure out how to do it.

Re:Parse, Don’t Validate by Doxin on Friday November 08, 2019 @04:03AM (#21480841)
> When people on your team are wasting time Googling lingo to try to figure out what kind of object they need, where to put a file, or where a method should go, it's a huge red flag.

I agree, but for a different reason. If you've got a team of programmers on a project without any understanding of what the client is doing you're bound to implement stuff ass-backwards from the clients perspective.

DDD is fine in enterprise, but the domain does need to be communicated to all involved parties. You can't just dump a codebase on someone and expect them to get to work, that only barely works for non-DDD codebases let alone DDD codebases.

Re:Parse, Don’t Validate by monoideism on Friday November 08, 2019 @07:06AM (#21481520)
The kind of DDD this article is describing is totally different from Java-world enterprise DDD. It's DDD done right, with no 50-member OOP classes. Just a single function that can only take a type that describes your domain in a way that prevents whole classes of errors.
Re:Parse, Don’t Validate by smt88 on Friday November 08, 2019 @11:07AM (#21483517)
I think we're on the same page.

When inheriting a purist DDD project written in C#, I came across several... interesting... charts, including this one:

https://jj09.net/wp-content/uploads/2018/12/ddd-diagram-exam...

A lot of members of my team couldn't figure out where things were "supposed" to go (or what most of the terms mean) after weeks of working on the code, so they just started slapping methods anywhere and worrying about it later.

Re:Parse, Don’t Validate by MrGilbert on Friday November 08, 2019 @02:34AM (#21480543)
> [...] trying to figure out what the hell DDD was prescribing, let alone trying to figure out how to prescribe it.

Well... If the carpenter needs to Google how to use a hammer and nails while at the construction side, something went terribly wrong, didn't it?

Re:Parse, Don’t Validate by btschaegg on Friday November 08, 2019 @03:11AM (#21480657)
I would actually agree with you there, but I suspect that wasn't your point.

A hammer is such a simple and obvious concept that it should not need to be googled. If anybody needs to do that anyway, you should not put the blame on the carpenter, but on the guy who "designed" the hammer.

On a related note, I still very much am convinced that Don Norman's Design of Everyday Things is a great read for anyone who designs APIs; types in this argument function both as affordances and force functions, which are the exact reason why a hammer is such an obvious tool.

Re:Parse, Don’t Validate by smt88 on Friday November 08, 2019 @03:28AM (#21480709)
You seem to be implying that a dev who doesn't understand enterprise DDD is unqualified.

That's not like a carpenter who can't use a hammer. It's like a carpenter who asks for a sketch of a project and instead receives a phone-book sized list of vague instructions that no one can agree on.

Re:Parse, Don’t Validate by MrGilbert on Friday November 08, 2019 @04:33AM (#21480946)
> You seem to be implying that a dev who doesn't understand enterprise DDD is unqualified.

I imply that a dev who doesn't understand DDD in a enterprise environment, is unqualified for working with DDD in an enterprise environment.

As much as a carpenter is unqualified to be a carpenter if he doesn't know how to handle a hammer and nails.

And I appreciate all the downvotes coming in.

Re:Parse, Don’t Validate by hmottestad on Friday November 08, 2019 @05:12AM (#21481068)
I don't think people agree with your analogy. To me your analogy is too simple. I have 6 years of java development experience and a masters in informatics. I have yet to work with enterprise DDD. There were no classes at university that taught it.

In most of my projects I have had to learn a lot of new stuff, it's a blessing if someone on the team knows how to use it already. However I have found that on most projects we've struggled to hire people with substantial experience with the tech stack and methodology that the customer had chosen.

We still wouldn't find an entire team that had experience with everything we needed even if we paid them ten fold the amount of every other company.

On the other hand I reckon every carpenter learns to use a hammer and nails in school.

Re:Parse, Don’t Validate by MrGilbert on Friday November 08, 2019 @07:35AM (#21481655)
> There were no classes at university that taught it.

So? You don't leave university and expect to be "done", right? You learn, learn, and learn - your whole software dev life. Even better, your whole life.

And no - nobody teaches you how to professionally handle a hammer in school. Now you are simplifying here. In school, they show you a hammer and nails. That's it. As much as they show you a compiler, a programming language and a basic architecture in university.

There are a ton of different hammers and nails out there, each with their own special attributes. You have an engineer's hammer, a tiling hammer, a rubber hammer, a roofing hammer, a splitting maul, a sledgehammer and so on... And I won't start talking about nails.

It's up to you to gain knowledge when to use what, and how to use it. That doesn't mean it's useless per se. Or overly complicated. It might just no "be your thing", which is fine.

Re:Parse, Don’t Validate by hmottestad on Friday November 08, 2019 @10:47AM (#21483274)
This was exactly my point. Not all carpenters would know how to use some specialised hammer and specialised nail. Just like most developers wouldn’t know how to use a specialised language and framework. So developers that don’t know how to develop with DDD would just learn as part of joining a project and they would still be qualified to be on the project. Just like how a junior carpenter might not know everything needed to erect a hose by themselves, but as part of a team of carpenters they would learn the things they didn’t know from school including those specialised hammers and nails for that specific house because the owner wanted something unique or what not.

FYI a carpenter in Norway needs 4 years of education to become a carpenter. 2 years in school and 2 years as an apprentice. If they don’t know how to use a bog standard hammer by that time they are not passing the final examination.

Re:Parse, Don’t Validate by MrGilbert on Friday November 08, 2019 @05:52PM (#21487766)
I see - maybe I got your point wrong at first. Sorry for the confusion.

Here in Germany, it's basically the same: A carpenter goes to school and work in a dual system for 3 years, and can then put a master on top of it after several years of working experience. This takes another 2 - 4 years and a ton of money.

Re:Parse, Don’t Validate by ewngzen on Friday November 08, 2019 @07:17AM (#21481561)
My take is that DDD is actually a convinient intuitive way to work with, if it is not, probably something needs to be discussed and refactor ed
Re:Parse, Don’t Validate by cjfd on Friday November 08, 2019 @04:52AM (#21481016)
This can go two ways. One can end up with lots of different types that do nothing but wrap a string. On the other hand I have also seen a float being used to represent a price. The correct way is somewhere in between those two extremes. If you have some logic specific to a value, by all means, make it a type but if there isn't it just ends up with lots of boilerplate.
Re:Parse, Don’t Validate by rzzzt on Friday November 08, 2019 @12:56PM (#21484871)
I've heard "micro-types" being mentioned in this context: https://markhneedham.com/blog/2009/03/10/oo-micro-types/
Re:Parse, Don’t Validate by mason55 on Thursday November 07, 2019 @05:38PM (#21478043)
Another good example of this is having separate classes for something like unsafe strings vs. safe strings in a web app. The functions which interact with the outside world accept unsafe strings and emit safe strings to the rest of the application. Then the rest of the application only works with safe strings.

Anything that accepts a safe string can make an assumption that it doesn't need to do any validation (or "parsing" in the context of the OP), which lets you centralize validation logic. And since you can't turn an unsafe string into a safe string without sending it through the validator, it prevents unsafe strings from leaking into the rest of the app by accident.

This concept can be used for pretty much anything where you are doing data validation or transformation.

Re:Parse, Don’t Validate by squeaky-clean on Thursday November 07, 2019 @09:41PM (#21479567)
Also a good way to prevent hashed passwords from being accidentally logged.

    Class PasswordType(django.db.models.Field):
        hashed_pw = CharField()
    
        def __str__():
            # you can even raise an Exception here
            return '<confidential data>'
Not that you should be trying to log this stuff anyways, but unless you're a solo dev you can't prevent other people from creating bugs, but you can mitigate common scenarios.
Re:Parse, Don’t Validate by user5994461 on Thursday November 07, 2019 @06:17PM (#21478364)
What are safe and unsafe strings supposed to mean? All strings seem like normal string to me, a "DELETE * FROM db" is no different from any other string until it's given to a SQL query.
Re:Parse, Don’t Validate by nostrademons on Thursday November 07, 2019 @08:14PM (#21479193)
Escaping modes. All strings are not equivalent: "Bobby tables" is very different from "'; drop table users; --".

The idea is to encode the contexts where a string is safe to use directly into the type of the variable, and ensure that functions that manipulate them or send them to outside systems can only receive variables of the proper type. When you receive data from the outside world, it's always unsafe: you don't even know if you've gotten a valid utf8 sequence. So all external functions return an UnsafeString, which you can .decode() into a SafeString (or even call it a String for brevity, since most manipulations will be on a safe string). Then when you send to a different system, all strings need to be explicitly encoded: you'd pass a SqlString to the DB that's been escaped to prevent SQL injection, you'd pass a JSONString to any raw JSON fragments that's had quotes etc. escaped, you'd pass an HtmlString to a web template that properly escapes HTML entities, and so on. It's legal to do a "SELECT $fields FROM tablename where $whereClause" if $fields and $whereClause are SqlStrings, but illegal if they are any other type of strings. And if you do <a href="$url"> where $url is an UnsafeString, the templating engine will barf at you.

There are various ways to cut down the syntactic overhead of this system by using sensible defaults for functions. One common one is to receive all I/O as byte[], assume all strings are safe UTF-8 encoded text, and then perform escaping at the library boundaries, using functionality like prepared statements in SQL or autoescaping in HTML templating languages. Most libraries provide an escape-hatch for special cases like directly building an SQL query out of text, using the typed-string mechanism above.

Re:Parse, Don’t Validate by leetcrew on Thursday November 07, 2019 @06:44PM (#21478641)
pretty sure mason55 is referencing (perhaps unknowingly) an example from joel on software. you can read more about it here: https://www.joelonsoftware.com/2005/05/11/making-wrong-code-...
Re:Parse, Don’t Validate by mason55 on Thursday November 07, 2019 @08:43PM (#21479339)
That’s the one, thanks for the link! I tried to find it while writing my post but couldn’t for the life of me remember a single thing to even try searching for. I probably last read that article when it was written in 2005.
Re:Parse, Don’t Validate by user5994461 on Thursday November 07, 2019 @08:08PM (#21479164)
Must have been about that indeed. Thanks.
Re:Parse, Don’t Validate by toast0 on Thursday November 07, 2019 @10:10PM (#21479687)
A safe string is something you got from the programmer (or other trusted source), and an unsafe string is something you got from the network/environment/etc.
Re:Parse, Don’t Validate by youerbt on Thursday November 07, 2019 @06:38PM (#21478585)
Then your database API should use "safe strings" only, simple as that.
Re:Parse, Don’t Validate by kortilla on Thursday November 07, 2019 @08:02PM (#21479134)
“DELETE * from table” is a safe string though for something like file contents or perhaps a comment box on a hacker news site.

The term “safe string” is effectively meaningless because it entirely depends on how the internals are going to use it.

Re:Parse, Don’t Validate by youerbt on Friday November 08, 2019 @04:01AM (#21480830)
But of course nobody is talking about universally safe strings. It's just a name to explain the concept.

Point being, if my database API uses the different types than my random internet input types, compiler will force me to convert/parse those.

Re:Parse, Don’t Validate by jodrellblank on Thursday November 07, 2019 @06:40PM (#21478608)
Are you genuinely curious, or are you being a troll?

Look at the content of your string, make a decision as to whether you would give it to a SQL engine. If you have not looked, it's presumed unsafe. If you have validated it - parsed it, in the context of this article and this discussion - and decided that you consider it safe, then it is a safe string from that point on.

This isn't a philosophical debate about what "safe" means to humans, it's a programming discussion that says if you only want to pass "select * from reports" to your database, check that's what the string contains before you pass it anywhere.

Re:Parse, Don’t Validate by kortilla on Thursday November 07, 2019 @08:04PM (#21479143)
Not sure if you’ve worked with databases before, but sql injection sanitization belongs at the SQL layer, not the user input validation layer.

If you’re doing it at user input validation, you’re doing it wrong.

Re:Parse, Don’t Validate by jiggawatts on Thursday November 07, 2019 @10:42PM (#21479797)
This!

It's impossible to do SQL-safety validation at any other layer, because otherwise you're making the assertion that someone with the last name "O'Neil" or "Null" (Yes! A real name!) may as well give up and legally change it for the "safety" of programmers that are too lazy to do thing right.

Re:Parse, Don’t Validate by user5994461 on Thursday November 07, 2019 @07:47PM (#21479077)
I am really not trying to be a troll. Genuinely don't understand this concept of safe strings.

How could a software even look at text content and determine safeness? There are cases where string input might be limited to just letters or numbers but often it's not. As soon as punctuation or unicode (non English users) is on the table, text is basically anything and there are no general defense from that.

Parsing and static types could have restrictions on string length, min or max value for numbers, how many items in an array, but it cannot make text safe generally-speaking by any meaning of safe. It has no awareness of how the content will be used.

Re:Parse, Don’t Validate by piaste on Thursday November 07, 2019 @10:52PM (#21479837)
We're not talking about some absolute, metaphysical "safe strings" that guard against every possible flaw, but rather about better supporting an already existing safety check.

If you never thought to write an escaping function in the first, you can't write a SqlString safe type either, obviously. Equally obviously, if you can write an escaping function but you can't write a function that detects a DROP TABLE, then you can write a SqlString type but not a SelectQueryString type.

The idea being discussed here is simply that if you do write an escaping function, its signature should not be (String -> String) or (String -> Boolean) or, God forbid, (String -> void), but something like (String -> SqlString).

This ensures that whatever you feed to your database must have gone through such an escaping function, instead of expecting the programmer to simply remember it. Also prevents you from accidentally escaping a string twice.

(Obligatory pedantic disclaimer: if you're working with modern databases, please don't escape your own strings and just use parameters instead.)

Re:Parse, Don’t Validate by jiggawatts on Thursday November 07, 2019 @10:37PM (#21479781)
I agree with you. The concepts of a safe string in isolation is too abstract too be meaningful. A correct API, such as interacting with a database only using explicit parameters (instead of string-concatenating to build up a query) is always safe, irrespective of the provenance of the input. The input could be a virus or a DB command and this would still be 100% safe.

What people mean by safe string in more specific contexts however, is meaningful, but the word "safe" is an unfortunate choice. Instead, think "SqlEscapedString" or "HtmlEscapedString" or "UriEscapedString". These are much more meaningful, and their use-case should be obvious. You can convert an arbitrary input "String" type into a "SqlEscapedString" and then safely use simple string concatenation to build up a query. This is useful in situations where non-parameter parts of the query are dependent upon the input in ways that are not safely exposed in the DB query API. For example, building up complicated WHERE clauses or using dynamic table names.

So you can write something like the following (in pseudo code):

    String tableName = ParseFromUntrustedPacket( packet );
    SqlEscapedString sqlTableName = new SqlEscapedString( tableName );
    SqlEscapedString query = SqlEscapedString.Unsafe( "SELECT * FROM " ) & 
        sqlTableName & 
        SqlEscapedString.Unsafe( " WHERE Foo is NOT NULL" );
    var result = connection.Execute( query );
The benefit of this kind of approach is that if that last function call has the signature of "Execute( SqlEscapedString q )", then it is basically impossible to accidentally pass an unescaped (unsafe) input string into it by accident. At every step, the developer is forced to make a decision to either pass in a potentially dangerous query snippet using "Unsafe(...)" or to make input strings safe by escaping them.

Similarly, this method converts Strings into a different type when escaping them, making it (almost) impossible to accidentally double-escape inputs, which is an issue commonly seen in some environments such as complex shell scripts.

ASP.NET for example does something similar with IHtmlString.

Re:Parse, Don’t Validate by jodrellblank on Thursday November 07, 2019 @09:43PM (#21479581)
Oh, then you're reading too much into "safe" and assuming it means "can never do any bad if used in any situation, must need an AI".

It's like the same way a software can look at a number that's going to control a water heater and determine whether it's a safe temperature for a human body or not. You the programmer chose some limits. When the user enters a number, it's an unsafe value by default, because you haven't validated it.

After you validate it, you have something which is 'safe' to pass around to anywhere in your code, like a security checkpoint says that random people are unsafe, and when they enter a building their details are checked, and then they are OK to enter and go anywhere inside the building.

You, the programmer, choose what things you consider safe and unsafe and those words mean validated or unvalidated, verified or unverified, checked or unchecked, approved or unapproved, known or unknown, outside or inside, or any other pair.

> it cannot make text safe generally-speaking by any meaning of safe

If something can't be done, ever, in any situation, that probably isn't what people are talking about doing.

Re:Parse, Don’t Validate by jcranmer on Thursday November 07, 2019 @08:05PM (#21479145)
The point that's being made here is if you make safe and unsafe strings separate types, in a strongly-typed system, it is impossible to use an unsafe string where a safe string is expected or vice versa. When you have a boundary function that turns an unsafe string into a safe string (e.g., escaping), or that rejects strings that are not safe, you can have a system where all the inputs are unsafe and are forced to go through such a mechanism exactly once to guarantee freedom from double-escaping issues.
Re:Parse, Don’t Validate by detaro on Thursday November 07, 2019 @08:03PM (#21479135)
I think the above definition of "gets turned into safe strings early" isn't necessarily a clear one.

The general idea is to separate strings into different types, with different rules. E.g. a HTML templating engine will always escape strings unless they're of a specific type (e.g. in Python a popular implementation calls the type "MarkupSafe") that says it's ok to include as raw HTML (e.g. because it's the output of a sanitizer), an SQL query builder will only accept specially tagged strings as non-parameters into queries, ..., which reduces the likelihood of the programmer accidentally using a string in a place where it isn't correct to use. Username field doesn't have any special rules attached? All code will reject unsafe use as far as possible.

Re:Parse, Don’t Validate by ioquatix on Thursday November 07, 2019 @08:07PM (#21479159)
Safe in the context of HTML means semantically significant characters are escaped correctly, including <, >, “ and ‘.
Re:Parse, Don’t Validate by tannhaeuser on Thursday November 07, 2019 @08:25PM (#21479246)
Depends on context: for content, only < needs to be escaped, within a tag (but not an attribute) > needs to escaped, within an attribute quotes of the same kind that started the attribute value (if any) must be escaped. Then there are legitimate cases of richly formatted user input/markup where you want to restrict script or block-level elements, or elements that can reach out to a container element such as a paragraph or section. I could go on here, but the point is to use HTML-aware template engines and markup processors, not rely on magic escaping routines.
Re:Parse, Don’t Validate by sedeki on Thursday November 07, 2019 @07:27PM (#21478970)
A string that is supposed to represent a ”name” in a web app context — safe or not? I am referring to potential SQL injections.

Surely, no names contain semicolons, but is the business logic-part of your app to determine that names which only contain A-Za-z (or whatever) are safe?

It is contextually dependent, meaning in practice as close to the actual SQL query as possible. Or call to file system, where dots are unsafe, and so on.

Static typing helps here as described in the article.

Re:Parse, Don’t Validate by agumonkey on Friday November 08, 2019 @04:08PM (#21486783)
Impossible invalid state typecheckeable
Re:Parse, Don’t Validate by zanny on Thursday November 07, 2019 @06:41PM (#21478612)
Rust is extremely good at this with newtype syntax and the ability to apply impls and derives to masking types.

Your JSON data might be a string, but having a Json type that guarantees its valid Json is way better. Same with stringified Base64, a constrained numeric value for a tunable, etc. Because using from impls on these types lets the compiler figure out almost all invalid type usages at compile time and give you eloquent feedback on it.

Re:Parse, Don’t Validate by lmm on Friday November 08, 2019 @04:53AM (#21481019)
Your comment gets the history hilariously backwards.

Actually using the type system has been standard practice in ML-family languages since at least the '70s. Simonyi described Hungarian notation as a way of, effectively, emulating a type system in less-powerful languages; describing Hungarian notation as "prefixing with the type" was not a mistake (as Spolsky claims) but an accurate description of how the technique was intended to be used.

The "Systems Hungarian" mistake came about because C programmers misunderstood the term "type" to refer to something far more limited than it does.

The technique in the article is not "encoding Apps Hungarian into the type system". It's doing the very thing that inspired ("Apps") Hungarian in the first place!

Re:Parse, Don’t Validate by Izkata on Friday November 08, 2019 @07:29PM (#21488500)
...Please re-read the part of my comment that starts with "The original intent"
Re:Parse, Don’t Validate by lmm on Monday November 11, 2019 @09:08AM (#21504892)
Thank you for your condescension. Please re-read Simonyi's paper. What you called "metadata" is in fact type. Please re-read my comment.
Re:Parse, Don’t Validate by goto11 on Friday November 08, 2019 @03:36AM (#21480739)
The original paper by Simonyi actually does describe prefixing with datatype. E.g. b for byte, ch for character, w for word, sz for pointer to zero-terminated string.

He specifically states:

The basic idea is to name all quantities by their types (...) the concept of "type" in this context is determined by the set of operations that can be applied to a quantity. (..)

Note that the above definition of type (which, incidentally, is suggested by languages such as SIMULA and Smalltalk) is a superset of the more common definition, which takes only the quantity's representation into account

So he is comparing to early object oriented languages where presumably Hungarian notation is not needed anymore because the type system of the language itself is rich enough to constrain the set of valid operations on the value/object.

So the "metadata" encoded in the Hungarian prefix is exactly what would be called type in a modern language. The idea of Hungarian was valid in a language with a insufficiently expressive type system.

I think the term "Typed Hungarian Notation" is really weird. Hungarian Notation is a workaround for a limited type system. "Typed Hungarian" is just... typed code.

Re:Parse, Don’t Validate by matt_kantor on Friday November 08, 2019 @10:36AM (#21483123)
> I think the term "Typed Hungarian Notation" is really weird.

I'm glad I'm not the only one. "Typed Hungarian notation" reminded me of "horseless carriage". :)

Re:Parse, Don’t Validate by DonaldFisk on Thursday November 07, 2019 @08:17PM (#21479202)
This helps the compiler, but only works for languages with type declarations, and is less helpful to the programmer, as to find a variable's kind (e.g. valid data vs. raw data) you need to look at its declaration, which may involve scrolling. The original idea, described in Joel Spolsky's original article on Apps vs. Systems Hungarian (https://www.joelonsoftware.com/2005/05/11/making-wrong-code-...) is that the programmer can see, in the expression that the variable is used or the function is called, that the code is wrong.

I apply a variant of Apps Hungarian in my own code, e.g.

    (setf input
          (inputOfEdge 
           (first (edgesOfSocket
                   (outputOfGate
                    (nth (position visibleInput (inputsOfVertex node))
                         (ingatesOfEnclosure enclosure)))))))
(In the system this is lifted from, node was confirmed to be a Vertex a few lines earlier, and Output is a subclass of Socket.)

The general idea is language independent: you could write similar code in Java or C.

Re:Parse, Don’t Validate by ttty on Thursday November 07, 2019 @08:28PM (#21479257)
No need to scroll. If you use a modern ide you can just hold Ctrl and hover the variable with your mouse.
Re:Parse, Don’t Validate by DonaldFisk on Thursday November 07, 2019 @09:57PM (#21479635)
That still wouldn't work for dynamically typed languages.
Re:Parse, Don’t Validate by squeaky-clean on Thursday November 07, 2019 @10:38PM (#21479784)
Maybe not something like Lisp but languages such as JS, Python, and Ruby have advanced enough tooling available that would easily identify this.
Re:Parse, Don’t Validate by marcosdumay on Friday November 08, 2019 @07:42AM (#21481701)
That's why the claim that it's an advantage of statically typed languages.
Re:Parse, Don’t Validate by Quekid5 on Thursday November 07, 2019 @06:09PM (#21478282)
I generally like this approach, but it's unfortunately really cumbersome in most mainstream languages like Java (and even Scala 2.x) or C#, but it works beautifully in Haskell because of two features:

- non-exported newtypes (also known as opaque types in Scala 3.x); this means your little module is in full control of instantiation of a 'parsed' value from an 'untyped' value. - DerivingVia (not sure if there's an equivalent in Scala 3.x); this makes declaring type class instances equivalent to the 'wrapped' value completely trivial.

These two features (and, I guess, the pervasiveness of type classes) in Haskell make this sort of thing as close to zero effort as possible.

EDIT: Looking at some sibling posts, I think my C# knowledge may be out of date. Apologies for that.

Re:Parse, Don’t Validate by endgame on Friday November 08, 2019 @12:41AM (#21480198)
I think you mean GeneralizedNewtypeDeriving, not DerivingVia. GND lets you pull instances through a newtype, trivially. DerivingVia lets you define your instance in terms of an instance on another newtype.
Re:Parse, Don’t Validate by runeks on Friday November 08, 2019 @04:11AM (#21480866)
DerivingVia is a generalization of GeneralizedNewtypeDeriving. The former can do everything the latter can and more. https://downloads.haskell.org/~ghc/latest/docs/html/users_gu...
Re:Parse, Don’t Validate by Quekid5 on Friday November 08, 2019 @06:11PM (#21487893)
Exactly. I intentionally avoid GND because it can be quite wonky, and DerivingVia basically subsumes it. You do still have to have slightly more explicit declarations of instances, but IMO it's worth it for the control.
Re:Parse, Don’t Validate by GuiA on Thursday November 07, 2019 @04:49PM (#21477679)
Here is a blog post applying a similar idea to matrix math:

https://www.sebastiansylvan.com/post/matrix_naming_conventio...

Re:Parse, Don’t Validate by shmageggy on Friday November 08, 2019 @04:56AM (#21481027)
I wish there were a type system for numerical computation that could encode things like rank and size of tensors and could statically check them before running. Currently, catching bugs requires running the code which can make for a slow development loop, plus it would make for a much more robust system than documenting these things in comments
Re:Parse, Don’t Validate by mezzode on Friday November 08, 2019 @01:50AM (#21480418)
https://github.com/google/mundane/blob/master/DESIGN.md was where I first learned about how useful opaque types can be for ensuring the type system does the heavy lifting
Re:Parse, Don’t Validate by lexi-lambda on Thursday November 07, 2019 @06:12PM (#21478322)
What you’re describe is in a similar vein to what is described in my blog post, and it’s often absolutely a good idea, but it isn’t quite the same as what the post is about. Something like NameType attaches a semantic label to the data, but it doesn’t actually make any illegal states representable… since there really aren’t any illegal states when it comes to names. (See, for example, https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-... .)

In other situations, the approach of using an abstract datatype like this can actually rule out some invalid states, and I allude to that in the penultimate section of the blog post where I talk about using abstract types to “fake” parsers from validation functions. However, even that is still different from the technique focused on in most of the post. To illustrate why, consider an encoding of the NonEmpty type from the blog post in Java using an abstract type:

  public class NonEmpty<T> {
    public final ImmutableList<T> list;

    private NonEmpty(ImmutableList<T> list) {
      this.list = list;
    }

    public static <T> Optional<NonEmpty<T>> fromList(List<T> list) {
      return list.isEmpty()
        ? Optional.none()
        : Optional.of(new NonEmpty<>(ImmutableList.copyOf(list)));
    }

    public T head() {
      return list.get(0);
    }
  }
In this example, since the constructor is private, a NonEmpty<T> can only be created via the static fromList method. This certainly reduces the surface area for failure, but it doesn’t technically make illegal states unrepresentable, since a mistake in the implementation of the NonEmpty class itself could theoretically lead to its list field containing an empty list.

In contrast, the NonEmpty type described in the blog post is “correct by construction”—it genuinely makes the illegal state impossible. A translation of that type into Java syntax would look like this:

  public class NonEmpty<T> {
    public final T head;
    public final ImmutableList<T> tail;

    public NonEmpty(T head, ImmutableList<T> tail) {
      this.head = head;
      this.tail = tail;
    }

    public static <T> Optional<NonEmpty<T>> fromList(List<T> list) {
      return list.isEmpty()
        ? Optional.none()
        : Optional.of(new NonEmpty<>(list.get(0), ImmutableList.copyOf(list.subList(1, list.size()))));
    }
  }
This is a little less compelling than the Haskell version simply because of Java’s pervasive nullability and the fact that List is not an inductive type in Java so you don’t get the exhaustiveness checking, but the basic ideas are still the same. Because NonEmpty<T> is correct by construction, it doesn’t need to be an abstract type—its constructor is public—in order to enforce correctness.
Re:Parse, Don’t Validate by Izkata on Thursday November 07, 2019 @06:25PM (#21478455)
Maybe I shouldn't have included the Java example, some others have jumped on it as well. That wasn't meant to be a summarization, but a similar idea in a different context.

You also seem to have missed the point of the Java example anyway, in a misses-the-forest-for-the-trees way. It was meant as a 1:1 example of an important result of your blog post, not an example of constructing the parse function:

> However, this check is fragile: it’s extremely easy to forget. Because its return value is unused, it can always be omitted, and the code that needs it would still typecheck. A better solution is to choose a data structure that disallows duplicate keys by construction, such as a Map. Adjust your function’s type signature to accept a Map instead of a list of tuples, and implement it as you normally would.

Using NameType instead of String is the same as using a Map instead of a list of tuples.

It was why I included AddressType in the Java example. Just like changing the function signature to not accept a tuple of lists and require a Map instead, forcing you to use the parse function to construct the Map, functions that only work on AddressType or only work on NameType can't receive the other one as an argument - where with a String, they could. They have to pass through the requisite parse function to convert String into a NameType or AddressType first, however those are implemented.

And I've seen the falsehoods lists before; "Name" and "Address" were simply the first thing that popped into mind while typing that up. Examples are just examples, and Name and Address are conceptually different enough regardless of the falsehoods that the main idea behind the example ought to get by anyway.

Re:Parse, Don’t Validate by lexi-lambda on Thursday November 07, 2019 @06:36PM (#21478562)
> You also seem to have missed the point of the Java example anyway, in a misses-the-forest-for-the-trees way.

Perhaps I did, yes. I do think the kind of thing you’re describing is valuable, to be clear. A lot of my comment was intended more as clarification for other people reading these comments than as an argument against what you were saying. I imagine that if I misunderstood your point, other people are likely to, too, so if anything, your clarification is generally a good outcome, I think!

Re:Parse, Don’t Validate by mcphage on Thursday November 07, 2019 @09:33PM (#21479531)
I believe Joel Spolsky discussed this in an article, having a wart on the name to represent if strings have raw inputs which are at risk of injection attacks.
Re:Parse, Don’t Validate by hnick on Thursday November 07, 2019 @09:37PM (#21479548)
I wonder why Taint Checking (https://en.wikipedia.org/wiki/Taint_checking) never caught on in more languages.
Re:Parse, Don’t Validate by mcphage on Thursday November 07, 2019 @10:59PM (#21479858)
I mean, I’ve got a pretty good idea why it never caught on in English...
Re:Parse, Don’t Validate by hnick on Thursday November 07, 2019 @11:16PM (#21479921)
It pre-dates the slang term by quite a while, unless it was around back in 1989? I don't recall seeing that online until the last decade or so.
Re:Parse, Don’t Validate by nereye on Friday November 08, 2019 @03:33PM (#21486423)
Wiktionary has it as far back as 1972, see https://en.wiktionary.org/wiki/taint.
Re:Parse, Don’t Validate by mcphage on Friday November 08, 2019 @07:41AM (#21481692)
Dictionary.com claims it dates back to at least 1977, but I have no idea.
Re:Parse, Don’t Validate by jolux on Friday November 08, 2019 @12:56AM (#21480247)
Seems less useful in languages with strong static type systems?
Re:Parse, Don’t Validate by mcphage on Friday November 08, 2019 @10:59AM (#21483436)
It requires a language with dependent types, like Idris.
Re:Parse, Don’t Validate by jolux on Friday November 08, 2019 @11:51AM (#21484043)
I don't think it does require dependent types, actually. Can't it be implemented as a monad? (possibly https://hackage.haskell.org/package/Tainted)
Re:Parse, Don’t Validate by hnick on Saturday November 09, 2019 @07:14AM (#21491065)
It exists in Perl. So I figure it can be implemented in any language.
Re:Parse, Don’t Validate by jolux on Saturday November 09, 2019 @01:18PM (#21493165)
Probably! But I think monads might make it more useful and ergonomic.
Re:Parse, Don’t Validate by breck on Thursday November 07, 2019 @06:41PM (#21478611)
I currently use this in my language "Grammar" (https://jtree.treenotation.org/designer/#standard%20grammar). In Grammar you can currently define two things: cellTypes and nodeTypes. Grammar looks at the suffix to determine the type. So if you are building a language with the concept of a person node and an age cell, you'd write "personNode" and "ageCell". "ageCell" might extend "intCell". I've found it a pleasure to use.
Re:Parse, Don’t Validate by papln on Friday November 08, 2019 @11:45AM (#21483958)
"Typed Hungarian" is just "Typed". The whole point of "Hungarian" notation was to workaround scenarios where the OP is impossible.

Your comment got an eyeroll from no less than Michael Feathers: https://twitter.com/mfeathers/status/1192771479332642816

Re:Parse, Don’t Validate by MuffinFlavored on Thursday November 07, 2019 @05:15PM (#21477898)
> making the language's type system handle the work that a person would normally have to think about in Apps Hungarian.

That sounds a lot like "type validation" to me, whereas the title of the article includes "Don't Validate"

Re:Parse, Don’t Validate by Izkata on Thursday November 07, 2019 @05:24PM (#21477963)
Read all the way down through the "Parsing, not validating, in practice" header. It eventually gets to examples exactly like mine, where "parse" means "transform into a different datatype so it can't be used wrong", while "validate" means "generate a message, but don't preserve that message in the type system in a way that's usable later".
Re:Parse, Don’t Validate by badfrog on Thursday November 07, 2019 @05:41PM (#21478059)
> That sounds a lot like "type validation" to me, whereas the title of the article includes "Don't Validate"

The variable name version does, sure. That's why OP said:

> The suggestion in this post is taking Apps Hungarian, and instead of relying on variable names, encoding it into the type system itself.

Making it clear that their example is different from what the article suggests.

Re:Parse, Don’t Validate by ericcholis on Thursday November 07, 2019 @04:50PM (#21477685)
My earliest programming experience taught me to use Systems Hungarian with scope. So, something like lcName for local character name.
Re:Parse, Don’t Validate by jacobsenscott on Thursday November 07, 2019 @05:21PM (#21477938)
On one of my first jobs all the class names were prefixed with C, but it wasn't carried through to variables or anything. I said we should stop prefixing class names with C and got shouted down. That's where I learned to mostly just do what I want without asking. Once you have 5k lines of something your way it is really too late for anyone to ask you to change it :)
Re:Parse, Don’t Validate by ronilan on Thursday November 07, 2019 @06:18PM (#21478381)
OT: My favorite movie quote:

let lastHungarian = ‘go’

run()

Re:Parse, Don’t Validate by Ericson2314 on Thursday November 07, 2019 @06:56PM (#21478739)
Your comment is wrong is wrong. You are talking about "encapsulation tricks", where you don't make illegal states unrepresentable, but just all the construction so you can audit than declare the unrepresented state won't be constructed.

Sometimes this is good, but the benefits are a lot lower, and many an overzealous programmer has taking the "boolean blindness" "string blindness" argument too far with copious newtypes.

Actually ruling out invalid states by construction, however, is way more valuable, and far more likely to be worth the work. It requires more thought than just newtyping away, but that's a feature, not a bug.

Re:Parse, Don’t Validate by Izkata on Thursday November 07, 2019 @08:58PM (#21479404)
Similar to some other replies, you've jumped to the Java example and made assumptions about it without reading the parts immediately before it.