1. Yes, I happen to think that the difference between this:
fn f() {
if foo && bar {
if foo {
} else {
}
}
}
and this:
fn g() {
if foo && bar {
h()
}
}
fn h() {
if foo {
} else {
}
}
is not worth talking about.
2. If we're talking about things like validate user input at the boundaries (and if you're a library developer, "user input" might refer to what the library users will pass in to your code), then I think that is a valid and useful guideline. If we talk about "don't spend time executing a bunch of code when you can exit early", then I'll also agree, although in most contexts, this doesn't really matter at the granularity of functions - but it does matter that you e.g. reject invalid input early on in your request handling (assuming a web app here) and not start processing it before deciding that you don't need to (with the notable exception of password validation, which should always be constant time).
3. What I mean by "big picture" is things like clearly delineating which parts of the codebase are responsible for what - for example, which parts of the code contain logic related to the database, which parts are related to business logic, which parts to interfacing with external APIs, which parts about handling responses. It's things such as "functional core, imperative shell" (Gary Bernhard) or other means to try to manage side effects. It's deciding whether to write blocking or non-blocking code, and in the latter case, how exactly to go about it (instead of making a total mess by mixing both styles with a lot of back and forth). It's about deciding on how you want to structure your test suite so it gives you the maximum amount of confidence.
4. I think ORMs provide mostly false confidence and outside of prototype scenarios, I wouldn't personally use them anymore - especially not ones like Hibernate and ActiveRecord - but, alas, it's not always my decision. Their biggest flaw is IMHO that they pollute your domain model (and sometimes even your presentation logic - looking at you, ActiveRecord) with database logic, just for the convenience of being able to call "save()" directly on an object. I don't terribly mind writing raw SQL (as long as you properly parameterize inputs), although I think that generally, type-safe query builders with a 1:1 relationship to SQL (such as jOOQ) are preferable. I do think that all of your SQL-related logic in your application shouldn't be scattered randomly across 10,000 files - it should be in a dedicated place (a number of files grouped in a common folder/package/module, maybe) so that if you need to review certain aspects of it (related to security or performance, e.g. avoiding N+1 queries), you don't have to hunt that logic down throughout your whole application.
2. If we're talking about things like validate user input at the boundaries (and if you're a library developer, "user input" might refer to what the library users will pass in to your code), then I think that is a valid and useful guideline. If we talk about "don't spend time executing a bunch of code when you can exit early", then I'll also agree, although in most contexts, this doesn't really matter at the granularity of functions - but it does matter that you e.g. reject invalid input early on in your request handling (assuming a web app here) and not start processing it before deciding that you don't need to (with the notable exception of password validation, which should always be constant time).
3. What I mean by "big picture" is things like clearly delineating which parts of the codebase are responsible for what - for example, which parts of the code contain logic related to the database, which parts are related to business logic, which parts to interfacing with external APIs, which parts about handling responses. It's things such as "functional core, imperative shell" (Gary Bernhard) or other means to try to manage side effects. It's deciding whether to write blocking or non-blocking code, and in the latter case, how exactly to go about it (instead of making a total mess by mixing both styles with a lot of back and forth). It's about deciding on how you want to structure your test suite so it gives you the maximum amount of confidence.
4. I think ORMs provide mostly false confidence and outside of prototype scenarios, I wouldn't personally use them anymore - especially not ones like Hibernate and ActiveRecord - but, alas, it's not always my decision. Their biggest flaw is IMHO that they pollute your domain model (and sometimes even your presentation logic - looking at you, ActiveRecord) with database logic, just for the convenience of being able to call "save()" directly on an object. I don't terribly mind writing raw SQL (as long as you properly parameterize inputs), although I think that generally, type-safe query builders with a 1:1 relationship to SQL (such as jOOQ) are preferable. I do think that all of your SQL-related logic in your application shouldn't be scattered randomly across 10,000 files - it should be in a dedicated place (a number of files grouped in a common folder/package/module, maybe) so that if you need to review certain aspects of it (related to security or performance, e.g. avoiding N+1 queries), you don't have to hunt that logic down throughout your whole application.