"Ask yourself why we are trying to plug defects with language features. The answer ought to be obvious. We are trying to plug these defects because these defects happen too often.
Now, ask yourself why these defects happen too often. If your answer is that our languages don’t prevent them, then I strongly suggest that you quit your job and never think about being a programmer again; because defects are never the fault of our languages. Defects are the fault of programmers. It is programmers who create defects – not languages."
Arrgh! Until we get out of this ridiculous, macho, victim-blaming mindset, software development will be stuck in the relative dark ages. More, better, safer languages, please!
[0] http://blog.cleancoder.com/uncle-bob/2017/01/11/TheDarkPath....
My point being: yes, if we'd be perfect drivers at all times and in all weather conditions there would be no more accidents. Luckily for us auto designers haven't adopted this perspective :)
"And because of this 'improved safety' we have millions of drivers out there who drive even faster and take even more risks, because they think the new cars are so much safer. "
(of course this comment is silly, the number of motor vehicle deaths per capita is about a third of what it was 50 years ago: https://en.wikipedia.org/wiki/List_of_motor_vehicle_deaths_i...)
Of course, it also depends on what the software is being used for. If I create a script for automating something just for me, I don't see any reason to add repeatable tests.
"All accidents are your fault. Got rear-ended? Shouldn't have been driving so slowly, or shouldn't have stopped. Got t-boned? Should have looked more closely at the intersection. Skidded on ice? Shouldn't have been driving so quickly, or turned so sharply. Yes, you avoided the pedestrian, but that isn't an excuse. In extremis, you shouldn't have been driving that day at all, and you do always have that option, so it's your fault regardless."
The line between empowerment and victim blaming is surprisingly thin. ;)
Now, that said, one of the ways you can work to prevent these things is to use better tools. Like languages that don't let you make those kinds of mistakes as easily.
You can take that same reasoning and say we should build web projects in C or assembly because any defects are our own fault.
Let's be honest. That's bollocks. It's just the same old "real programmers use X" line. I'm sure there's an XKCD that parodies it.
Sure we need more discipline. Who doesn't? Yet that discipline is far better spent on doing what the compiler can't. It makes no sense doing what a computer can do unless it's really necessary. That's why we're programmers after all, right?
I think that exact argument applies to designing ever-safer, ever-better languages. You might never have the perfect tools that ensure 100% program correctness, but it's sure as hell what a tool-maker should aspire to.
And as a (completely hypothetical) competitor of yours, I would support you using a language that encourages you to fuck up frequently.
> proving to the compiler that this thing is actually compatible with that thing
I used to have this opinion, but nowadays I think that time is actually spent proving to myself that I'm right, which is always a good thing.
Having a compiler to do the hand holding is not such a bad thing, because the alternative is println-development.
What happens in a dynamic language is that you have to load in your head the shape of the data your working with, the API and everything really. Your head can't hold that much for anything that is bigger than a simple script, so you have to constantly execute and verify (in the REPL, in the browser, with a unit test, etc) each line of code that you write, before writing the next line of code.
This is why people complain about compilation speed in Scala, Haskell, etc, even if they miss they point, because even a slow, static compiler will improve efficiency, since you no longer have to compile and execute each line of code before you write the next one.
And yes, in my experience this is exactly what happens in big code bases built in dynamic languages, short of being really sloppy and introducing lots of bugs.
I really don't know where that canard comes from. My test suites rarely if ever explicitly test compatibility.
They test for specific values: if I do this and that, do I get the value that I expect. The type "test" gets covered implicitly, because if it's not the correct type, it will also not be the correct value.
My teams don't use ORMs anymore. I've found that all of the time we "save" by not hand-writing SQL is instead lost fighting with the ORM, and problems with SQL are a lot easier to Google.
I've also found that the ability to swap databases quickly is almost totally unimportant. 100% of the time we're targeting SQLite and PostgreSQL. I don't need a few extra thousand lines of code so I can theoretically support SQL Server running on a toaster in some kid's dorm somewhere.
I think StackExchange's Dapper [1] works similarly in the .NET world.
Though, I generally prefer a non-religious approach to ORM mapping anyway. Use Hibernate for the stuff that it is good at. If you find it awkward for some particular service, don't be afraid to grab a DB connection and do a bit of SQL (maybe even using Hibernate's powerful rowmapper functionality) when it is easier.
Any ORM is going to be a little rough in some cases (even ones you write yourself) and none fit all problems perfectly.
Sure, but that's a bit circular. I find that a sensible default is to write the code to match the data, not abstract the data to fit the code. Because, if nothing else, you'll want to understand that data with another language or framework. If it's a one-off Java project that will get thrown away in a few months, whatever is fine, but most Java applications (especially enterprise Java) aren't throwaway projects.
Do you know what works in pretty much every language? Do you know what will be supported in 30 years? SQL queries.
Hibernate is good at some things, but if we think in terms of product lifetimes and not sprints, I think SQL is a much lighter dependency.
But you know what has consistently provided a nice abstraction that works really well for 90% of cases (even if you start with DML, as you should)? Hibernate :)
I've used plenty of homegrown frameworks, and they just never are quite what their originators crack them up to be.
A database is just another application. SQL is just another Turing-complete programming language.
The ORM is just an big fat thing that sits on top, and from which you only use 10% of the functionality it provides, but in theory each app uses a different 10% so it justifies itself...
ORMs can be ok... as long as you don't build business logic on top of and inseparable from it!
(As an example of horrible use of ORMs: some frameworks have ORM systems with an events system on top... god have mercy on your soul if you make the mistake of using this system to implement business logic, and end up with it accidentally depending on db connection and caching details, and not having time to refactor when you realize this! ...but if you avoid the trap, you can reap the benefits of the functionality that the ORM provides, while moving your logic at at a whole different layer of the app - hint: just invent a new "XBizLogicServices layer" or whatever and not import framework stuff into it if you can't find a better design, it will at least be easily testable.)
I was just pointing out that if you use one you do receive protection from injection attacks. Just because only part of the ORM is actually performing the protection doesn't change the fact that you have it as a consequence of using the ORM.
You can also get the same protection by using a SQL library that supports prepared statements. But ORM's still provide that benefit.
(Not a frequent contributor to comments/ here on HN. Mostly like to read.)
What you are referring to is a statement I frequently make -- 100% coverage is the goal. It's an asymptotic goal, but it's still the goal. No lesser goal makes any sense.
I am not sure that 100% can be called an asymptotic goal, given that you cannot even get close, for real systems. Once you recognize this, you can start having a realistic discussion about what you actually will be able to test for, how best to allocate your limited resources, and what other steps you might take to mitigate the consequences of this unfortunate fact. It means that methodologies bassed on extensive testing must justify this use. An additional benefit is that we might be able to discuss what we can do to improve software development without the sort of dogmatic non-sequitur that I mentioned in my first paragraph.
What is a goal then? A maximum? A desirable attribute?
I'd argue a fixed percentage target of any kind doesn't make sense, much like measuring productivity by lines of code.
http://blogs.tedneward.com/post/the-vietnam-of-computer-scie...
Sure, and lots of people end up implementing a lisp in C++. Doesn't necessarily mean they should just use a lisp instead. Usually it just means they should learn how to use their tools idiomatically.
"The sooner you admit that you can't fit the whole program's source code in your head, the sooner you can begin incorporating that into your design."
Page 3:
Summarizing: as a slow-witted human being I have a very
small head and I had better learn to live with it and to
respect my limitations and give them full credit, rather
than to try to ignore them, for the latter vain effort
will be punished by failure.
The Humble Programmer: http://www.cs.utexas.edu/users/EWD/ewd03xx/EWD340.PDFPage 11:
The competent programmer is fully aware of the strictly
limited size of his own skull; therefore he approaches
the programming task in full humility, and among other
things he avoids clever tricks like the plague.
He expressed similar thoughts on other occasions. And there are others who express the same idea.I also want programmers to be able to use those tools well.
Finally, I look at a lot of crap code written by programmers who throw all their disciplines away because of schedule pressure or other factors. For the sake of going fast they throw away everything that might allow them go actually go fast.
Lets take for example ORMs and Hibernate in particular. I can't tell you how many times I've seen horrors related to ORMs / Hibernate, because of an actual mismatch between relational data and object graphs, but then developers are made to feel guilty because they "aren't using it right", made to think that only if they switch this setting on, use this and that annotation, read a book or two, everything will be alright going forward.
Most such projects fail from a technical perspective of course, because the developers having invested so much time in those shitty techniques, exploration of alternatives becomes unfathomable to them, because all of that effort which can span years ends up being unjustified. And I suspect that Uncle Bob is guilty as well.
Lets take TDD as another example. I remember a time when TDD was religious dogma, which was unbelievable, because I couldn't see actual TDD in projects of companies advertising TDD in job descriptions. Much like Agile, Scrum and all that crap, it usually doesn't work because, as the masters will quickly tell you, you're "not doing it right". I've seen a single project where TDD was implemented by the book, but the developers where wasting so much time on testing stuff, including endless discussions, that they were forgetting TDD wasn't the actual artifact they had to deliver.
Now Uncle Bob tells me that we don't have the discipline required. That's not surprising. I’ve been hearing this argument in some form or another for years.
The surprise is the attention that we are paying to what Uncle Bob has to say.