Why not program right?
bertrandmeyer.com
bertrandmeyer.com
Yep. If we actually valued correctness, the market would place some cost on incorrectness. Security is a common example of this. If we wanted, we could punish software developers or publishers for shipping security bugs (for example, making them liable), and then we would see an immediate shift in how software was written.
That's not necessarily an endorsement of that position (it lacks enough nuance to even be remotely considered a good idea), it's just a fairly illustrative example.
Sw quality is so poor across the board that there is almost no one producing high quality, reliable software. My bloody phone can't properly select text in this box for example.
Sw companies have optimised their production for decades to develop software that's just good enough to ensure profit and they've trained customers to expect and accept poor quality.
Is anyone surprised when Windows reboots for updates in the middle of an important presentation? No, that's how Windows works.
Companies will even reduce quality to improve profits and still get away with it if the customers don't notice, don't understand or are too apathetic to take action.
Often there is no action to take that will sufficiently punish the offending company.
Security is a great example: it's been bad for so long that core pieces of technology are fundamentally insecure and can't be significantly improved without total rewrites. Punishing developers and companies would result in a collapse of commercial software development, so humanity collectively accepts that software is by nature insecure.
But it's no longer your problem.
So, please don't take it personal, but 'the well intentioned types who write these articles' tend to be the people that then get called in to clean up the mess.
And then - belatedly - the job gets done properly to keep the company in business, assuming there is still time enough to do so.
Just this week I had a nice inside look at the kind of mess gets left behind when the original duct-tape-and-spit guy leaves the company and lets his former co-workers clean up their mess. It isn't pretty, and a chapter 11 isn't an unlikely scenario, so forgive me if I take a harsher than usual look at the attitude that causes this sort of thing.
Note that the 'free market' doesn't have a horizon much longer than the next quarterly shareholder report, and that your typical software product lives a multiple of that interval. So software made with short term goals in mind will create long term headaches.
Your two week marketing campaign gets a pass. But your decade long backend project does not, nor does your real time medical device controller, ECU, database system or operating system.
If that were a problem in reality, the markets would be punishing companies where that happens. It's not a real problem that that happens. Management pretends to be upset, but in reality it's not a huge deal. Entropy is normal in apps and everything else. To continue the analogy from my original comment, do companies really go into crisis mode when one of the many cars in their fleet inevitably "collapses"? No. They build or buy a new one and life goes on.
> nor does your real time medical device controller, ECU, database system or operating system.
Yep. Those are the rare cases I talked about. It's a tiny fraction of total programmers building databases and stuff like that.
My programming career has gone from "I don't know the best way to write something", to "I know the best way to write something and I'll do it this way every time", to "often it doesn't fucking matter, just get it done and move along to the next problem".
But for many applications it does matter and for those cases you are essentially creating technical debt that will someday be somebody else's problem.
You've got a project manager breathing down your neck, pressure to deliver functionality, you've explained the technical debt issues etc - and you're still told to do it the wrong way.
Then years later, the only thing on the code is your name and some very dodgy looking decisions. That project manager is still probably kicking around blaming people and earning a fortune hehe.
Do the right thing and quite that toxic work place. You will help natural selection: extreme corner-cutters should go out of business. I knew a guy (programmer) who destroyed a company by simply leaving.
You can only tell a shoe craftsman to create shoes out of cow dung and grass for so long.
Most of what we do in this market is reading some form data, JSON, XML, parse it, read/write to a database or some other API, gather results, send them back to the browser as either HTML or JSON.
I checked right now when it was the last time I had to devise some clever algorithm. I was at the end of 2015 in a Rails project. I remembered all the stuff about invariants from my CTO back in 1995 and it did really help. However in this market that's a once in 10 years occurrence, unless one keeps grinding through coding interviews on artificial problems (because those companies are affected by the streetlight effect.)
So, from my point of view "for most applications it does not matter, but for a few of them it does." It probably matters when writing some of the algorithm in the web browser I'm using right now.
Sometimes creating technical debt is the right decision. Sometimes it's "get over this budget hump using two devs instead of five or we go out of business". And then you do get over it and all of a sudden the company is hugely successful and it's a good problem but you're working really long hours just trying to keep up with helping all that cash flow in... the real world rarely makes conditions so perfect you can write perfect code.
I strongly dislike it when I make the decision to create tech debt, but I will at least leave comments or documentation for the next guy on the parts I think could use more love.
And it's rare I do create it. I actually spend a large part of my time refactoring code and making it better and reducing technical debt. It's one of my favorite things to do. And that points right back to my original post. You know what's interesting about the code I refactor? It's working code. It solves the problem. I wouldn't want to build something bigger on it without refactoring. But I also wouldn't curse out the guy who wrote it. He solved the problem at the time within the budget and time constraints and other competing requirements he was juggling. Good for him.
Seems you are judging from the SV / startup / USA bubble. Most of the world works in VERY different conditions than that.
I mean yeah, bosses whipping their devs for maximum throughput happens everywhere but the combination of factors you describe seems to be specific for USA.
A lot of startups are actually obsessed with quality to the point of failing. I've seen that. I've also seen the opposite. There is a lot of variation in the myths founders create that they follow like a religion because they believe it's the one trick they need for success ;-)
You do eventually run out of money. It's so much more important to ship something to customers to get some feedback than it is to get it perfect. It's a very tricky balance to get right though. It has to look and work good enough to not scare potential customers away.
I don't disagree, that's unequivocally true.
As a programmer myself however I know that "I'll get back to it later and fix it" is usually a lie...
Haven't founded a business yet and I think I'll do that eventually but it also seems that "do your market research first and foremost" is an universal rule.
EDIT: As an European I should add that most of us never start a business unless they already have several customers willing to pay lined up in an orderly queue. I feel that too many Americans (probably not only them) start a business based on pure enthusiasm and hand-waving that motivated them during a few business events where people vaguely expressed an interest in their idea.
Oh they do, I can show you plenty of examples. But it is never the problem of the people that created the issue in the first place.
Think of these things as time-bombs of technical debt. They'll blow up sooner or later, usually later, and that makes it that much harder to deal with the fall-out.
Also: for all the lessons about economy made here: I would happily argue that doing things right is actually cheaper in the long run and possibly also cheaper in the short term, by applying the techniques described in proper measure you can save yourself a ton of headache.
But of course that would first require a basic understanding of what the article is trying to put across, which if your time horizon is short and your deadlines are looming likely isn't going to be on your agenda.
> It's a tiny fraction of total programmers building databases and stuff like that.
Software you build tends to live longer than you think and tends to be incorporated into places that you can not foresee when you make it.
The 'tiny fraction of total programmers building databases' should include the huge fraction of programmers building embedded systems, APIs, operating systems, libraries and so on. All of those will have life-spans in the decades if they're done halfway right.
And you're a bit assuming and rude. Your argument also isn't as bulletproof you want to make it sound. What is the argument here, anyway? There's no need to improve technique for an average programmer because an outlier system (Facebook) is written in a language commonly associated with poor programming practices, with some handwaving about markets and entropy sprinkled on top?
What's the argument here? That stakeholders have requirements that don't have to do with robustness like budget and deadlines and that your software has a shelf life and sometimes it's ok if it eventually breaks, just like cars and even the laptop I'm typing this on will. Is that an unreasonable perspective?
And Facebook is an outlier? Really? Even when we add Wordpress, Wikpedia, Flickr, MailChimp and a long list of the most successful websites in the world to that list?
Yes, FB is an outlier -- one out of million companies. Only 5-10 companies out of those millions made this current model work. So their existence and "success" proves absolutely nothing.
You have a strange understanding of the word "successful".
Facebook is certainly not "successful" because it neglects good tech. If anything, they rewrote PHP itself so as not to have to rewrite their customer-facing software. How is that for your "tech excellence is not important" argument? They rewrote the damned runtime and even added a compiler.
So please define what "successful" means to you. "A lot of people using FB" is a temporary metric, even if it lasts for decades. It's not sustainable per se. It relies on hype and network effect. These fade away.
@jacquesm's points are better argued than yours. Throwing words like "free market" and "entropy" does not immediately prove a point.
I will give you the historical fact that there are many throwaway projects but he's also right that the fallout from the tech debt they incurred is almost never faced by the original author. Throw in the mix the fact that many businessmen are oblivious on what do the techies do in their work hours exactly and one can be easily misled that technology perfection is not important. Seems that you did.
Final point: I am not arguing for 100% technical excellence. That would be foolish. We would still be refining HTTP and the WWW in general even today and internet at large would not exist. But the bean counters have been allowed to negotiate down tech efforts to the bare minimum for far too long, and it shows everywhere you look.
(My local favourite restaurant waiters' smartphone-like devices for accepting and writing orders are faulty to this day because some idiot bought a cheap consumer-grade router AND made the software non-fault-tolerant, being an everyday example.)
Stats? Evidence? I mean hundreds of of thousands of companies use PHP and other forms of less than perfect tech.
Websites all over the world seems to get the job done even when JavaScript with all its warts is used. I like JS for the record, but it does have warts.
> even if it lasts for decades.
You're saying the same thing I said. That stuff breaks. That companies come and go in and out of fashion. I also think it's interesting that you're calling FB an example of tech excellence but saying it's going to fade away. Choose one?
> How is that for your "tech excellence is not important" argument?
I never made any such argument. Not even close. I only said quality is not the only requirement and might sometimes not be a requirement at all.
Most of the code I write is high quality. I put a lot of effort into code reviews too. I mentor more junior devs around quality. My original post is actually much more nuanced than you are claiming.
> Final point: I am not arguing for 100% technical excellence. That would be foolish. We would still be refining HTTP and the WWW in general even today and internet at large would not exist.
Exactly. That's in the spirit of my original post. Maybe re-read it to see that we mostly agree instead of making my position into something it really isn't?
Oh, I meant companies at the scale of Facebook. There aren't too many of them, would you not agree?
> I also think it's interesting that you're calling FB an example of tech excellence but saying it's going to fade away. Choose one?
FB does a lot of open-source projects. Their devs are excellent. That doesn't mean that their main value proposition is not comprised of code of the kind you speak about. No need to choose one, both can coexist in such a huge company like FB.
> I never made any such argument. Not even close. I only said quality is not the only requirement and might sometimes not be a requirement at all.
Well alright then. I am not here to pick a fight, you should be aware that you came off a bit more extremist to me and a bunch of others than you claim. But these things happen, I can't claim your intent because of a few comments, that's true.
Me and several others' point is that quality plays a part bigger than what you seem to claim. I also knew many devs that decided they won't ask for permission to take the [slightly / much] longer road and this decision paid off many times over in the following months and years.
Sometimes businessmen simply must not be listened to. I can ship it next week alright. But I can skip a few vital details, namely that I did not take into consideration some stupid micromanagement attempts to teach me how to do my job ("nobody cares about this arcane thing you call 'error logger' or 'fault tolerance', just get on with it already!"). Such toxic work places should be left to rot, that is a separate problem however.
You're hilarious. On an annual basis I end up being the deciding factor in the allocation of a fairly large sum of VC money and tech quality is a big deciding factor in that.
Fortunately there are plenty of successful companies that do a much better job than what you are describing you are doing.
Every piece of software should be high quality even if it's a throw-away website used for 2 weeks? You'd expect the programmer to give a mathematical proof for the website code?
I also described that stuff does eventually break like the laptop I'm writing this on and it's not end of the world. We expect stuff to break.
Can you explain why my wife and almost every accountant in the world amortize intangible assets like in-house developed software and give it a useful life span?
That's learned behaviour post factum. Had we (the software industry at large) done better then they wouldn't have the countless examples to learn from and turn them into a habit. Don't conflate things.
> I also described that stuff does eventually break like the laptop I'm writing this on and it's not end of the world. We expect stuff to break.
You are arguing extremes. The fact that a physical object will eventually suffer wear and tear no matter what has zero correlation to the fact that most software can be much more robust and long-lived but extreme time and money constraints prevent it from being so.
Our points of view can meet but not until you admit that a learned behaviour is something that can be changed if enough people with money stop turning cutting corners into an olympic sport.
Nonsense. Stuff breaks. Everything. Even stuff made to a very high standard.
> most software can be much more robust and long-lived
It can't. Not because it can't be much more robust. But because most software is simply obsolete after a few years or maybe ten years if you're lucky. Software doesn't live in a static world where nothing changes. Laws changes, accounting practices are modernized, entire industries come and go, and everything is in a constant state of change. Maybe you haven't been around long enough to see it. I have. I've seen perfectly built in-house custom inventory software replaced a few years later by something like SAP because upper management decides the pros of having an integrated logistics system far outweighs the features of one in-house app. Sorry, but I've been in the business world far too long to fall for the idea that software is ever long-lived. There are some rare cases that it can be. The 40 year old COBOL programs some banks run to process massive amounts of transactions over night. And guess what? As long lived as they are, they are being re-written little by little because it's damn hard to find anyone under 65 who is actually interested in maintaining them. Software does not live in a vacuum.
I'd say producing one durable piece of tech vs. 5-10 non-durable pieces of tech is still more sustainable for the environment, would you not agree?
I'm not sure how we would require products be durable though? Who would be Czar of how durable things must be? Seems like that person would have a huge amount of power over which industries are profitable and by how much. I'm open to ideas though.
In any case, regulations have proven time and again to mean absolutely nothing unless enforced very strictly and with a very heavy hand (flat percents of the offender's gross income, and I mean from 20% and up, not some petty 1-2%). But that won't happen -- lobbies, rings of companies, "anonymous" donations, things like that... the status quo is too deeply entrenched. But we can dream, right?
Quite the opposite: markets have been rewarding it for some time. The richest companies mostly had buggy software. What got them revenue was everything but flawless quality. Then, once their customers were locked in via other tactics, the customers kept paying them so long as the software continued to work with a switch costing too much. They also often patented anything that could block competitors.
Even quality-focused customers often want specific features even if it leads to occasional downtime. Also, releases improving on features fast. I think Design-by-Contract with automated testing can help plenty there with the pace necessary for competitiveness in a lot of product areas. The markets don't care about perfection, though. The company's priorities better reflect that.
So, the management at these companies operates in a market that barely cares about security or mostly cares about appearances/perception. The incentive structure rewards working against quality or security. The costs are externalized with little happening to counter that. So, the rational actors ignore quality/security as much as they can. Programmers should act no different in a system if maximizing selfish gain or minimizing work.
Personally, I'm a utilitarian that considers security a public need. I strongly favor regulations and liabilities to increase the baseline of our security. Just cover the basics like memory safety, input validation, secure admin interfaces, error handling, backups, and recovery if nothing else. The stuff we can already do today with free tools that the suppliers just don't care about. That's not what the market is, though. So, I can't blame people in it for giving it what it wants if they risk losing money or perishing focusing on idealistic goals. I do encourage those doing business with utilitarian style, though. It ranges from easy to hard work they don't even have to do. Also especially glad when I'm one of their customers. :)
I'm a strong advocate for liability for software producers because it seems we as an industry are categorically incapable of doing the right thing. Until it directly affects the bottom line this likely won't change.
Customers are not 'ok with the status quo', they're clueless, and the only thing that changes is corporate profits.
In the end the difference between doing it right and doing it wrong is more related to long term vs short term thinking than that it would affect the bottom line in a more dramatic fashion (such as would be the case with liability).
> I'm a strong advocate for liability for software producers because it seems we as an industry are categorically incapable of doing the right thing. Until it directly affects the bottom line
These two statements seem to contradict each other. If it's not directly affecting the bottom line today, how would one go bankrupt?
I do agree with you there should be some force pushing to eliminate this negative externality. We could compare poor security practice with toxic waste. In general the force I'm talking about is government that creates smart regulations. You'd like to do it by allowing consumers to sue after the damage has already been done. I'm not going to get into that debate, but both of us have proposed solutions and I agree either would be an improvement over what we have today.
The market isn't a static, designed thing. It's an organic beast that will change and consume you if you don't change with it.
>[...]
>And then, five years after you've left the company and some system inevitably collapses with nobody having a clue as to what went wrong you'd finally realize the wisdom of all that.
So guy puts up a web site for $500 in consulting fees that is a 2-week project. It makes the company $7 million over the next 72 months because it becomes literally the biggest inbound channel.
Are you saying he shouldn't have built it for $500? What should he have done?
But ... code has to be maintainable, meaning it should be simple to the person that maintains it next. Typically that means no cleverness and no obscure languages or frameworks. Choosing eiffel only makes sense if you know the next maintainer will be proficient at eiffel.
Choosing Eiffel makes the next maintainer proficient in Eiffel by definition, because that will be the job requirement for the maintainer position. Unless the people responsible for hiring cheap out, that is.
What you're advocating here is optimizing solutions strongly towards being maintainable by cheap, interchangeable workforce. It's a valid goal - presumably one the management would like - but sometimes (often) it's not worth the extra cost in complexity, both early and later on.
(Tangentially: programming is a profession. It should be entirely expected of people to be able to learn new things on the job.)
I personally did that few times in my career: accepting job with technology I barely knew at the time, because I thought it would be fun to learn it.
You can imagine how that usually works out: software written by someone who was learning the programming language on the job.
As the original commenter who started this thread, I'd like to make it clear that I agree with you and I don't write quick and dirty code. Or at least very rarely. Even for stuff that has a very short shelf life, I write code that usually has very few bugs and that I'm usually proud of because of exactly what you said: I've done it so often it's a habit now.
I've always strived to write the best quality code possible within the constraints. Sometimes those constraints were even my own lack of knowledge. But after three decades of doing this I'm starting to think I'm actually getting to be pretty good at it. ;-)
So I wasn't suggesting to just write bad code in my original comment. Just to have a broader view of where quality goals sit within the many competing stakeholder requirements. A programmer who doesn't let perfect be the enemy of good is a better programmer.
Those are pretty good bellwethers for the effects of bad technical management.
The problems with market!perfection are many - mostly resolving around short-term optimization, externalities and lack of alignment between market values and human values. But we have brains that can be used to get better outcome than what the market incentivizes by default.
Almost all bugs, security of otherwise, are just negative externalities. I think the public has been conditioned to accept that software not only comes with bugs, but many of them, and there's nothing that can be done about it. Companies/developers/publishers are not penalized much at all for buggy software, so much so that it's a common business tactic to deliver crappy software that doesn't even accomplish what it states it does, much less bug free and without security problems, with the understanding that it can be fixed up after delivery with little negative consequences.
As for a proof that this is happening, there are plenty of examples if you look at the highly competitive spaces and consider goods you usually buy, and how they evolved over past decades. Food and tools are two obvious cases that come to mind.
This applies to many professions we consider a craft. I'm sure some guys slamming up 2x4s for carbon copy houses in the suburbs would rather be building timber frame homes with inlaid custom woodwork.
I see markets like combustion. A powerful force if you can contain and channel it, but an absolute disaster if you let it roam free.
That's the thing, this doesn't happen in real world and it is questionable if the concept of correctness is useful at all. As it is based on unvalidated and incomplete assumptions about the world, never fully correct themselves. Sort of correctness of incorrectness.
But popularity and fashion are not disembodied forces controlled by the whims of the gods. They are the sum total of decisions made by people. We could make different choices, but the belief that this is futile is a self-fulfilling prophecy.
Upper IT management can't just say "we're switching to Haskell because fewer bugs". They have to sell the idea to the folks who will pay for those massive changes which include retraining existing employees. And management does take into consideration how big the hiring pool is. That affects costs. A surge in demand for Haskell programmers would of course create a higher cost for hiring and keeping them.
So they continue to hire Java programmers and students graduating from uni make sure they know Java.
Where is the opportunity for us to make different choices?
Should students refuse jobs in Java? Or without picking on a language, jobs at companies that have the highest software quality standards? That's a lot of idealism and responsibility to ask of someone whose is just hoping they can get a foot in the door and start their career.
Or is there someone else you have in mind that could be making different choices? It does seem like my own personal choice to give up on Java has had zero effect on its popularity.
There is far more at play than the "the belief that this is futile is a self-fulfilling prophecy" although I agree that too is a factor.
I do have hope though. One thing I've seen happen is more and more programmers who were introduced to functional programming at uni and who manage to sneak ideas from that in wherever they can. I think we are slowly moving away from the worst parts of the object oriented paradigm and adopting the easier and better parts of functional programming.
I'm looking forward to see what we end up with. So far, I think the evolution has headed in the right direction and we are getting better and better at this thing we call coding.
By exercising our free will. By having the courage to stand up and say, "Yeah, I get that we have a huge investment in Perl code, but Perl really sucks so how about we do this new project in Python instead? Or Scheme? Or Common Lisp?" Or, "Yeah, I get that we can get it done faster by doing it in Java, but that will incur a huge amount of technical debt, and also make it so that the really cool kids, the ones who get why Java sucks, won't want to work for us. So how about we make an investment in our future and try Clojure or Scala or Rust instead?" If enough people do that, eventually one of these overtures will get a green light. Whatever organization does that first will eventually accrue a competitive advantage, and that will in the fullness of time change the dynamic.
But it won't happen if no one even tries.
Did you miss the part of my comment where I said I gave up Java and C++ for reasons of code quality? That was well over 15 years ago. I am doing my part actually.
I've had the "courage" to talk to management countless times in my career about what I think the best choices would be to improve quality. I don't even think it takes courage. It's just a conversation and attempt to sell an idea. Happens all the time in business.
Do you think my description of the challenges around getting change to happen were more accurate than the parent's "the belief that this is futile is a self-fulfilling prophecy."?
I hardly think my comment claims it's futile when I concluded with being hopeful that change has and is happening.
No, but the bulk of your comment sounded pretty defeatist to me:
"These choices are rarely made by developers"
"No one ever got fired for using Java"
"Where is the opportunity for us to make different choices?"
"It does seem like my own personal choice to give up on Java has had zero effect on its popularity."
It's true: a single person's decision to stand up against the system is unlikely to have an effect. But if everyone makes that choice, it will have an effect. And that is more likely to happen if more people stand up and say that you should make that choice rather than whine about they tried and failed.
That's because you're asking the wrong questions.
"Is there anything I mentioned that's not a realistic assessment? Is it me that's negative, or is it the actual situation?"
Those are the wrong questions. The answers to those questions don't get you any closer to a solution to the problem. They only get you to the conclusion that the situation is hopeless and that you should give up.
OK, you want an answer? It is both you and the situation that is negative. But the reason that the situation is negative is because of people like you who have decided that the situation is negative and that the only reasonable thing to do is to give up. And you know what? You're right. That is the only reasonable thing to do. Which means that the only way to solve the problem is to be a little unreasonable and carry on despite the fact that it makes no sense.
That's why I'm doing things like this:
If you think you have the right answers to change a globe full of programmers and to make businesses focus more on software quality, then by all means you should go on to prove to the world you are right.
I'll continue to assess the situation realistically and do my thing. I've never once failed to point out to management when I think things are being done poorly. I'm often the new guy on the team who starts measuring and reporting tech debt to management. You're super quick to judge a stranger based on a few comments in a forum.
When I put the concerns of the company first (instead of being idealist and obsessive about quality as the only goal that ever matters) management takes what I say seriously. So when I do speak up about quality they listen. That's my path. Fine that yours is different.
Maybe if you asked more questions and attacked less you'd find that those who you think are your enemies are actually allies and just have a different idea about the best way to improve things.
So I went back and re-read your first post:
> How could we make different choices? These choices are rarely made by developers unless it's their own startup.
That sounds very negative to me.
> For most IT jobs these kinds of decisions are made by upper management who have to answer to a board of directors, and ultimately to shareholders.
Ditto.
> No one ever got fired for using Java.
Ditto.
> Upper IT management can't just say "we're switching to Haskell because fewer bugs". They have to sell the idea to the folks who will pay for those massive changes which include retraining existing employees. And management does take into consideration how big the hiring pool is. That affects costs. A surge in demand for Haskell programmers would of course create a higher cost for hiring and keeping them.
Ditto ditto ditto.
> So they continue to hire Java programmers and students graduating from uni make sure they know Java.
Ditto.
> Where is the opportunity for us to make different choices? Should students refuse jobs in Java? Or without picking on a language, jobs at companies that have the highest software quality standards? That's a lot of idealism and responsibility to ask of someone whose is just hoping they can get a foot in the door and start their career.
Ditto.
> Or is there someone else you have in mind that could be making different choices? It does seem like my own personal choice to give up on Java has had zero effect on its popularity.
Ditto.
> There is far more at play than the "the belief that this is futile is a self-fulfilling prophecy" although I agree that too is a factor.
Mostly ditto.
And then, after wading through that sea of negativity, we finally get to this:
> I do have hope though.
Very well, I acknowledge that in your first post you talk about where you think the promise is coming from. But do you see how someone might come away with the impression that you were not entirely optimistic about it?
I've never thought an accurate description of the current environment and the challenges around changing it are a pessimistic view of things. Nor optimistic. Just realistic. I prefer realism. Is that bad?
If you want to see it as negativity, I think that says something more about you than me.
One of the reason I described all of those things AND asked questions is because I was hoping someone would actually come back with some stories about how they have overcome those challenges.
Saying that Java is still the most popular programming language only because people haven't tried enough seems to me to be both inaccurate and dishonest, and does nothing to help change that. Clearly what we've done in the past has changed nothing. Time to look at what we missed and to try something other than "just do it".
If we really do want to use better programming languages and techniques (I'm pretty into TDD myself) then it's very important to understand what management thinks about those ideas and why, and how we might influence the real decision makers. I've tried the wrong way enough times in my career to to understand the right way. Selling an idea to upper management usually has to come with low risk and a guaranteed return on investment.
That's neither optimistic nor pessimistic, neither positive nor negative. It's just the simple truth. Don't kill the messenger.
So lots of people are inclined to say things like, "then don't be lazy, do the work and think deeply"—but for one thing, 'deep thought' should be considered as a conserved resource and you have to choose what to spend it on (it's not automatically better to always spend it); and for another, I think the actual depth required for perhaps the majority of real-life problem domains is impractical, or perhaps sometimes the domain is even fundamentally not amenable to an elegant mathematical solution. So you have to contort the 'better' language to do inelegant things it's not really suited for anyway.
I think the constraints on the 'triples_from' structure from the article is a bit misleading and makes a good example of what I'm talking about. It looks super simple, but if you note how this constraint
across tf.item as tp all tp.item.source = tf.cursor_index end
is actually working, it's not so much that the language gives a particularly elegant/powerful means of specifying these constraints as it is that 'triples_from' was structured in such a way that it would be easy to specify the constraint. My feeling is that trying to do this for real-life things would rarely ever be so neat.If the domain you're modeling has mathematical elegance to begin with—absolutely, do the deep thought and uncover the invariants. But if it doesn't, then you'd be 'programming wrong' by trying to use such techniques.
The alternative I've been thinking about is just developing far more powerful/pervasive visualization tools so that you can write relatively mindless imperative code and just see where things are going wrong more easily. (consider the author's example of multiple data structures which must be kept in sync, but it's hard to tell when they get out of sync). Not trying to self-promote too much but you can follow my profile to the project if you're curious.
I.e. size of arrays or "nonblankness" of strings, or balanced invoices.
The simple fact of thinking about the constraints, will help design code.
I wasn't making the case that we should always abandon quality. Just that we understand its relative importance to other business requirements. That we don't build a $2,000 lock for a $10,000 safe to protect $1.
I'd like to think the majority of code I write is high quality. I am proud of most of the code I write. And I spend a lot of time helping junior devs refactor their code to be more robust, deal with edge cases, and be more maintainable, etc.
I've also been in the industry for a few decades now, and I'm more excited than ever about the opportunities for quality. The code we were writing in COBOL back in the day is nowhere near the level of quality of code that can be written today. Hell, we weren't even measuring bugs and quality back then.
I encourage you to have a look around for opportunities where your employer's values and goals are better matched to your own values and goals. If you are super interested in software correctness, you shouldn't be building throw-away websites for short-lived marketing campaigns. But that doesn't mean those jobs aren't important too. Just that you shouldn't be the one doing them.
What software wisdom would you share with us instead? That projects have deadlines and budgets? That the perfect solution does the job at the lowest cost over time? That the right way to program is to take the customer's requirements into consideration?!
Honestly it looks like you gave up a long time ago and you're just trying to convince the rest of us that mediocrity is the way to go. No thanks.
And it's not like Meyer is advocating for some hardcore formal verification... he's merely pointing out that design by contract can improve software quality. The same DbC which has first class support and could be implemented in many languages. Even the C++ boost library recently added support for DbC; it's kind of ugly and probably bloats the object files, but it's there.
That's exactly how I summarized most of his comments yet he still claims it's not true. I don't know, I am interested if he will reply to some of my comments so we can better judge what he actually had in mind. Him claiming that everybody misunderstood him is not a helpful discussion starter. :)
I love programming. And I've been at it for three decades. Zero burn out. I don't believe in just ship it, and I take a lot of pride in my work. And yes, part of that pride comes from having a better understanding of customer requirements than someone idealistically insisting we cannot ship working software because the aesthetics of the code aren't pleasing enough yet. That's why I get paid a lot more than idealistic junior devs. Whose idealism I do appreciate, and who I enjoy mentoring. Most of that mentoring being around how to improve the quality of their code... I never said to ignore quality.
Does it sound like I'm saying the world doesn't need idealists when I said this in my original comment?
"So this article is good (although I think you're really looking at functional programming by this time in history) but first make sure a top priority is program correctness before getting into the mode suggested by the article"
Maybe it's your own cynicism that gave you such an ungenerous interpretation of what I thought would be helpful advice to other devs. Whatever it is, that's on you, not me.
Yeah we know that not all projects can be built to the most stringent quality standards. The reality is that a lot of them have piss-poor quality though: they crash, lose data, get easily hacked, etc.
And when that's the reality the software engineering profession dooesn't need somebody preaching about requirements and keeping a balance between quality and other concerns, it needs quality fanatics.
I agree there are some people willingly ignoring the positive things I said in my original comment, and the other positive things I've said in other comments. My guess is that they would rather my view not be nuanced because otherwise there's not much left to attack. I'm happy to try to correct any misinterpretation, but I don't think it's all on me because it's not all comments that disagree with me. Quite a few comments show that people are getting my nuanced view. I would encourage you to re-read my very first comment with an open mind and decide if it's a balanced view based on decades of experience, or if I was actually really saying quality isn't important. If I was, it's very strange I would say the article in question is good. Which I did say.
I disagree that the software profession needs quality fanatics. The software profession needs quality fanatics when it makes business sense. Nobody ever stayed employed by building a $2,000 lock on a $1,000 safe to protect a $1 bill. What you built might be of the highest quality, but when you build with blinders on and ignore every other business requirement you aren't a fanatic for quality. You're irresponsible. I take pride in my ability to do what's best for the company. It's often difficult and requires making tough decisions and tradeoffs and risk management and making sure everyone involved is aware of all of those things. That's what a professional looks like. Not a perfectionist obsessed with quality to the point they become difficult to work with. Don't let perfect be the enemy of good.
> The reality is that a lot of them have piss-poor quality though: they crash, lose data, get easily hacked, etc.
Not the projects I'm on. I refuse to ship code that is that bad. I will get fired first.
I disagree strongly. I would say that software development is a tire fire. Every day there are reports of bugs in software causing all kinds of real-world problems. These days software bugs can kill people[1]. And there are only going to be more CPUs and more software and more bugs going forward.
> Markets have already mostly figured out the rare cases when such robustness is really needed.
I don't see how this is a supportable statement in a world that includes the "Toyota Unintended Acceleration" bug? (Among so many many others.) When you say, "a perfect solution according to markets is the solution that does the job for the lowest cost over time" aren't you effectively saying we should only expect software to be as good as has to be to protect the liability of some corporation? Not to take a cheap shot, but uh, I think the families of the people who died in the car accidents-- excuse me, collisions ("'Accident' implies there was no one at fault.") --might have a different attitude to software correctness?
In any event, your entire argument is predicated on the idea that correct software is expensive. But this is only true because we, as an industry, have not made effective use of the the available tools to write correct software!
It's not expensive to write correct code. It doesn't take longer either. We just don't do it.
Dr. Margaret Hamilton figured out how to write bug-free software as a side effect of her work on the Apollo 11 program years ago and nobody noticed.[2] (She's the person who coined the term "Software Engineer" BTW.) Byte-for-byte, flawless code is no more expensive than buggy code. And maintenance costs are near zero, so it's actually cheaper. You just have to use the right method (which has existed for about 30~40 years, nearly totally ignored.)
Please PLEASE don't make excuses. We've can get this right, even if "the market" doesn't notice or care.
To reuse my lumberjack metaphor from my other comment: Chainsaws exist. They are safer and faster than axes. There is in fact no way that cutting down trees with an ax is objectively better than cutting down trees with a chainsaw.
You are maintaining that, since trees are felled well enough with axes today, there's no sense in investing in chainsaws and chainsaw training, not now, nor ever in the future.
You're saying that "the market" only really needs wood cut by axes and doesn't value wood cut by chainsaws because all the furniture made with it is good enough, and we should just live with splinters and chairs that break and drafty houses, etc...
Frankly, it's kind of a lame argument to find on a pro-tech forum. Fancy sophisticated technology is awesome, unless it threatens to obsolesce your favorite ax, eh?
> you have to be able to find qualified developers, and what developers learn is based on popularity and fashion.
This is the source of the problem: we're not "engineers", we're not even car mechanics! We're barely above the level of kids building go-carts in their backyards out of junkyard parts. We should be ashamed of our fashion-driven-ness. The amazing thing is that we got the business people to go along with this![3]
Maybe someone should just start offering chainsaw-cut wood at cheaper prices than the hand-hewn crap and see if "the market" likes that noise? (In case I'm being too arch, that's exactly what I'm about right now. I'm so freaking passionate about this.)
"Program correctness" shouldn't have to be "top priority" because it should be the default. You should get it "for free" along with the software for the same price because it costs nothing extra.
[1] For example: "A Case Study of Toyota Unintended Acceleration and Software Safety" Prof. Phil Koopman. September 18, 2014. Carnegie Mellon University https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_...
[2] Nearly nobody noticed. I know it sounds crazy but it's true: There's a simple, easy method to develop bug-free software. James Martin wrote it up in a book "System design from provably correct constructs: the beginnings of true software engineering." in 1985. That's probably the best source if anyone wants to read up on it.
[3] A programmer in language or framework A who cannot or will not learn language or framework B is not a good programmer. (I don't mean putting "Won't do PHP" on your resume, I mean that you can't or won't learn it in the first place.) Q: "What if we can't find Python devs? There are so many Java devs. We should use Java." A: "Why would you hire a Java guy who can't do Python? Even to do Java?" I've had that conversation a bunch of times.
Business is another thing, nobody convinced them to go along with anything, it's the other way around. Incentives to produce software the way it is produced actually come from businesses as they are the ones paying for it. Engineers just go along with it.
I get that software industry is very dogmatic and it's hard to see things for what they are. But we should at least try.
I'm using "correctness" to mean software that is bug-free.
The system that the software is a part of may still have problems, but none of those problems should be caused by bugs in the software components. It's also possible to build bug-free software that solves some other problem than the one you have. Both of those issues are orthogonal to the issue of why the industry doesn't adopt methods that generate bug-free code.
> Yours is just one such method, and one of the expensive ones.
I expect to be able to train normal, non-programmer folks to be able to use it (a HOS-like system that permits elaboration of a top-level spec into bug-free working code) to develop bug-free programs. If that works it may be so cheap that it depresses the market for "real" programmers. I should be so lucky.
But regardless, these methods (HOS, Cleanroom, etc.) just aren't that dreadfully expensive. And bug-free code, once written and paid for, can be reused. The cost analysis has been on the side of "provable correctness" for longer than my lifetime.
> This is very important distinction if you want to understand why "proving correctness" cannot get anywhere.
Well I don't accept your assumption that '"proving correctness" cannot get anywhere'. My whole point it that it has gotten places and we're all ignoring it because we prefer to use e.g. C and Java and {{POPULAR LANGUAGE}}...
> For a lot of software even if we need reliability there simply exist more objectively better ways to achieve it.
If you are talking about "reliability" of software I don't know what that means other than bug-free.
I know you can build reliable systems out of unreliable parts, but to do that there still has to be some reliable system orchestrating them and compensating for failures.
But again, I'm not saying there's a method for reliable systems, only reliable software. The absence of the former doesn't invalidate the existence or desirability of the latter.
> Business is another thing, nobody convinced them to go along with anything, it's the other way around. Incentives to produce software the way it is produced actually come from businesses as they are the ones paying for it. Engineers just go along with it.
The "suits" aren't to blame for this one. They only know what we tell them (to a first approximation.) If you tell your boss, "I can chop better with this ax than that chainsaw." you're lying or ignorant. How is management supposed to even know the possibility is there if the programmers doesn't tell them? Or they bring it up and the response is "Sure, I'd love to use {{TECH}} but {{EXCUSE}}."?
There's a cost for bugs. If you can get bug-free programs for the same upfront cost as buggy ones (and my whole argument is that we can, but don't) then there's no upside and only downside to accepting buggy software, and methods that permit buggy software to be written.
We could use chainsaws, instead we use axes and claim chainsaws are too expensive and axes cuts fine.
It's not because the bosses, who only care about board-feet[1] per worker per hour, are too cheap to buy chainsaws.
[1] "The board-foot is a unit of measure for the volume of lumber in the United States and Canada. It is the volume of a one-foot length of a board one foot wide and one inch thick. " ~https://en.wikipedia.org/wiki/Board_foot
As an example, here's a way to get Logical Paradigm programming in your favorite language http://minikanren.org/ It's simple, easy to understand and implement, and you can use it to do things like type inference and type checking with flexible and powerful constraints to define and ensure invariants and stuff like that. This stuff isn't expensive or even that challenging, we just don't do it.)
I do get the point of your analogy, but it's really a very poor analogy.
> If you can get bug-free programs for the same upfront cost as buggy ones (and my whole argument is that we can, but don't)
This sounds like a massive market opportunity. One then wonders why absolutely no one has exploited the opportunity. There's something missing here.
All of human history is a tire fire then. Most stuff around the world is poorly engineered and just gets the job done. Wooden bridges with rope and wire holding them together and no analysis whatsoever done on what load it can bear. For most of history those bridges made up the majority of the bridges in the world. And it worked just fine until modern transport put higher demands on bridges. Yet, you still find clunky wooden bridges all over the undeveloped world, and they continue to work.
Should we try to do better? Of course we should. But someone has to pay for it. It doesn't happen magically.
Regarding the Toyota Unintended Acceleration bug, that's gross negligence if the top priority coming from management wasn't quality and if someone can prove that, they should end up in jail. And I would not excuse the developers either. I would never ship code that I know might kill someone. I would rather quit and work as a cashier. Please re-read my original post because I never said quality isn't important. I only said that quality is not always a top priority, and that in some cases it should be a low priority. A website for a 2 week marketing campaign will never kill anyone. It would be a waste of resources to insist on anything other than just shipping it once it works.
If you're honest with yourself and look around, you do it all the time in your own life too. You draw a diagram on a piece of paper or a white board to explain a concept and then you throw it away or erase it. You don't carve it in stone just because it will last longer and someone a hundred years from now might find it useful. You put up a simple rope barrier to keep people from stepping on newly planted grass. You don't erect the wall of China. Temporary "low quality" solutions that will later be dissembled and thrown out (or save the rope for reuse at least) are often the best fit based on the requirements.
> You just have to use the right method (which has existed for about 30~40 years, nearly totally ignored.)
I'm very skeptical that markets would completely ignore an opportunity to beat the competition if the costs were exactly the same but the results were higher quality. But I'm going to look into this. Thanks for the reference. I'm going to read James Martin's book and see if I learn something new that will help me write better code.
Yes. (We have spent the last 10,000 years recovering from the Younger Dryas and we are only just now getting back on our feet. Heck, most of us still think agriculture is a good idea when really it's about the dumbest way imaginable to relate to the soil. But I digress.)
> Most stuff around the world is poorly engineered and just gets the job done. Wooden bridges with rope and wire holding them together and no analysis whatsoever done on what load it can bear. For most of history those bridges made up the majority of the bridges in the world. And it worked just fine until modern transport put higher demands on bridges. Yet, you still find clunky wooden bridges all over the undeveloped world, and they continue to work.
Ah, but none of those bridges are built out of electrified math.
Software is electrified math and it can be perfect.
And it's self-referential: we can write perfect meta-code that emits only perfect code.
> Should we try to do better? Of course we should. But someone has to pay for it. It doesn't happen magically.
My point is not that we never try. My point it that the world contains many attempts and most of them have been ignored by most working programmers.
> Regarding the Toyota Unintended Acceleration bug, that's gross negligence if the top priority coming from management wasn't quality and if someone can prove that, they should end up in jail. And I would not excuse the developers either. I would never ship code that I know might kill someone. I would rather quit and work as a cashier. Please re-read my original post because I never said quality isn't important. I only said that quality is not always a top priority, and that in some cases it should be a low priority. A website for a 2 week marketing campaign will never kill anyone. It would be a waste of resources to insist on anything other than just shipping it once it works.
Let's assume, for the sake of argument, that I'm wrong and correct software always costs more than incorrect software. In this scenario (which may well be the REAL scenario) you have put your finger on the important bit: we're talking about the location of the inflection point.
Allow me to reference Randall Munroe, "Is It Worth the Time?" https://xkcd.com/1205/ It's a handy chart that shows, "How long can you work on making a routine task more efficient before you're spending more time than you save? (Across five years)"
It's not precisely what we're talking about, but it's got the same flavor: how much do you expect to use the buggy software vs. the cost of correctness...
Now my point would be: The industry should have had a house-on-fire urgency around reducing the cost of correctness to shift the infection point downward so that all but the most trivial software can be made correct economically.
We should have been doing that since forever (or at least sometime after the Apollo 11 mission.) Instead we generally ignore these sorts of things.
> If you're honest with yourself and look around, you do it all the time in your own life too. You draw a diagram on a piece of paper or a white board to explain a concept and then you throw it away or erase it. You don't carve it in stone just because it will last longer and someone a hundred years from now might find it useful. You put up a simple rope barrier to keep people from stepping on newly planted grass. You don't erect the wall of China. Temporary "low quality" solutions that will later be dissembled and thrown out (or save the rope for reuse at least) are often the best fit based on the requirements.
Have you been to Daiso? It's the Japanese dollar store. Pretty much any human problem that can be solved by ten ounces of plastic can be solved in Diaso for $1.50. I'm not generally into consumer culture, but I love Daiso.
You don't need 'temporary "low quality" solutions' if you have Daiso.
It's not that I don't use hacks, or don't respect them, it's that we're so far behind where we should be in terms of off-the-shelf solutions (to programming) and we don't seem to be quick on the uptake...
> I'm very skeptical that markets would completely ignore an opportunity to beat the competition if the costs were exactly the same but the results were higher quality. But I'm going to look into this. Thanks for the reference. I'm going to read James Martin's book and see if I learn something new that will help me write better code.
God bless you! (I collect powerful ideas and I cannot tell you how many times people have said, "If $FOO is so great, why doesn't everybody use it already?"... I don't know! I don't freakin know! It makes me sad. All of human history is a tire fire, indeed.)
- - - - - - - - - - - - -
This is my reply to your later comment on this same thread.
First, wow, I'm impressed. You are actually doing the homework and I tip my hat to you with great respect. Seriously, that's the nicest thing you could have done and I really appreciate it.
Second, yes the language and presentation around these "HOS" ideas has apparently always been really bad, with the issues you describe. It also doesn't help that the necessary background knowledge and jargon wasn't wide-spread at the time.
Third, yes it was panned by Dijkstra and the Navy, I've read both of those reviews, and their objections are not without merit. But, and I say this as someone who has huge respect for Dijkstra, they were both wrong: they both missed the fundamental advantages or "paradigm", if you will, of how HOS et. al. works.
(Also, have seen that Simon Peyton Jones interview. And no, we're not just talking about Functional Programming, that's kinda orthogonal. E.g. Haskell helps you write code with fewer bugs, HOS prevents them in the first place. Another way to differentiate them is that if you're typing text in a text editor to make software you're not doing HOS regardless of the langauge.)
So, poor marketing, bad reviews, obscure principles and the general disinterest of industry led to this powerful technology languishing.
Yet, I insist there's something there. Let me try to convey my POV...
In modern terms I can describe the crucial insights of the HOS sytem concisely. Here goes:
Instead of typing text into a flat file of bytes and hoping it describes a correct program, the HOS method presents a tree of nodes that is essentially an Abstract Syntax Tree (but concrete and there's no driving syntax because there's no source text.) The developer edits the tree using only operations that maintain the correctness of the tree.
This is like "Par Edit"[1] in emacs, or a little bit like some of what J. Edwards is attempting with Subtext[2], or the old "syntax-directed programming environment called Alice"[3] for Pascal. (Again, it's not that no one has ever tried anything like this, my whole point is that powerful techniques for writing software with fewer bugs in have been around for a long time and we, in general, don't use them.)
The main difference from these is that HOS uses a very simple and restricted (but Turing complete) set of operations to modify the tree: Sequence, Branch, Loop, Parallel. (There are some "macros" built out of these operation for convenience but underneath it's just these four.)
Starting with a high-level node that stands for the completed program you gradually elaborate the tree to describe the structure of the program and the editor/IDE enforces correctness at each step. You literally cannot create an incorrect program.
Apparently normal people, accountants and such, could sit down in front of the IDE and,with a little training and coaching, learn to describe their own work processes in it and essentially write programs to automate (parts of) their own work.
I've been working towards bringing this to market, on and off, for years now. In fact, my first programming job was the result of a talk I gave on a prototype IDE at a hacker convention about fifteen years ago. I have just finished implementing type inference and type checking for my latest vehicle: a dialect of the Joy programming language. It has been slow going (I lead a chaotic life) but I'm on the cusp of having something I think will be really great. If it works, it will revolutionize software development.
Quixotic, I know, but somebody's gotta tilt at those windmills...
Anyway, thank you again for taking the time to look into this. I can't tell you what that means to me personally. I know the "Provably Correct" book is terribly written, but I urge you to try to look beyond that. All I can really honestly tell you is that I'm convinced there's something really important and useful there.
[1] "ParEdit (paredit.el) is a minor mode for performing structured editing of S-expression data." https://www.emacswiki.org/emacs/ParEdit
[2] http://www.subtext-lang.org/
[3] "In a syntax directed editor, you edit a program, not a piece of text. The editor works directly on the program as a tree -- matching the syntax trees by which the language is structured. The units you work with are not lines and chracters but terms, expressions, statements and blocks. " https://www.templetons.com/brad/alice.html
Interesting discussion. Thanks. I will keep my eye on this space from time to time.
Check my submissions in a month or two, I'll put in a "Show HN" when I have something to show.
Here's Edsger Dijkstra debunking the books written about HOS.
https://www.cs.utexas.edu/users/EWD/transcriptions/EWD08xx/E...
An evaluation by the US Navy concluded. "the HOS literature tends to advertise their ideas and products more than making a contribution in substance to the field of Computer Science. The author recommends that USEIT not be used in the TRIDENT program or any program development at NSWC. Even for a high level system specification, USEIT is not seen as a good choice. A mathematical functional notation or a PROLOG-like notation appears better suited for that purpose. The examples in the Appendices of this report, especially Appendices C, D, and E, show that a LISP-style mathematical notation is more compact and normally easier to read than the control map notation of USEIT. On a more positive note, the author considers the functional approach to system development and programing very promising. Systems so conceived and programs so constructed are more amenable to analysis and therefore, in principle, more reliable and better manageable."
http://www.dtic.mil/dtic/tr/fulltext/u2/a198753.pdf
So are we just talking about functional programming when we say HOS? If so, the pros and cons of functional programming have been discussed at great length.
Here is an interview with Simon Peyton Jones (one of the creators of Haskell) talking about why Haskell is "useless". It's a short interview worth watching if you want to understand the nuances and challenges and costs around creating high quality and bug-free software.
It's understandable when it's a physicist or electrical engineer trying to code something up to get something working. What really upsets me is when it's professional software developers who never evolve out of that mindset.
I feel like at the end of the day the trick is to think algebraically -- Your data types and structures are some domain and you define operations over the elements of that domain in such a way that certain properties hold.
I mean, this is a bit like saying, why doesn't every physicist do everything by just coming up with a random differential equation for their problem then use fixed points to deduce the long-form non-recursive version and isolate out the wanted variables into long form ? It's, after all, usually by far the simpler process, especially since everyone can come up with a few differentials for any situation. Coming up with the correct long form directly, however, is absurdly hard. So if you simply learn to work with differentials, that's the way to approach essentially any problem. With a tiny caveat ... "learn to work with them" is 6 months of study and intensive practice, and that's assuming you already know a lot of math that isn't exactly high school level either, including a significant list of "tricks" that you just need to know by hard. But what you can do with it is amazing.
But the level of knowledge and understanding required is just too high for anything resembling general application.
Don't look at other videos until you've internalized the first sentence. Think long and hard about what that sentence means : differential equations allow you to find any function that you can make enough "what happens when it moves" observations about. Enough usually means one.
For instance you can find Newton's equations from the statement that "falling things keep going linearly faster" (because they're the simplest function that satisfies that differential equation).
On the more complex side, Google's pagerank is also the solution to a differential equation. Very technically it sort-of kind-of qualifies as a first-order one, just not in the real number space.
There's a separate branch of "differential equations" (let's call it "the physics branch") that studies how to work it with discrete time intervals rather than continuous ones, which is also interesting and useful.
I think the bigger problem is that when people work in large groups for implementing a business logic, things are assumed invariant in one component of a system, not tested for in another component that relies on that condition, and what used to work ceases to work when that condition changes.
If it literally isn't labeled "invariant" explicitly in some documentation, people learn to practice 'defensive programming', after enough frustration. Or they feel compelled to understand all the code in their code base, or migrate over to smaller companies, smaller projects where this is less of a headache (but not really, because we all depend on pieces of systems we can't always inspect in totality, therefore, can't always assume we know everything about the systems we are dependent on).
The real world has edge cases. If the instructions are wrong, it's because either the invariant isn't actually an invariant in the real world, or the domain is modeled incorrectly. The higher up you get in writing programs about programs, the less likely it seems like real world data works this way, because you literally don't even have the common sense or perspective to see that some things change without being able to specify an underlying order to them (implying some things change without there being an order to describe their changing).
“A post can’t be published if it hasn’t been reviewed.” (Precondition)
“After submitting a payment, an audit log entry must be created” (post condition)
This is what I've seen in interviews. The typical recent grad can understand an existing model. Some of them can't design a simple model from scratch and concretely specify functions to do operations on it.
if the program doesn't do what they want it to do, either the instructions are wrong, or there need to be more of them to handle the cases that aren't currently handled.
I've asked interviewees what they could do about them cycles in user-entered code, by giving them a 2-node example. Far too often, they reply with an if-clause to detect exactly a 2-node cycle. Then I ask what to do about 3 nodes, then far too many of them try to give me a 2nd if-clause!
With a 2-node example what do you mean? Like a race condition? A mutex or some kind of lock to prevent this?
When you say node cycle. Do you mean like in graph theory where you can have the "fast and slow traversal" find a cycle?
Because this is not what writing software is about. Ultimately it is about trying ideas out, where the notion of an invariant doesn't have a place. Why do you believe it should?
Are you saying that if the code doesn't solve the problem the wrong thing to do is add more to it? What about when you have multiple options, you can't just avoid adding more instructions necessarily?
Can you give a real example about what you are talking about?
Part of me is thinking that you are saying new grads are not readily able to come up with a clever solution and instead brute force. But you are not saying it in so little words, or in any intelligible way to me.
This stuff is useful is when you have lots of modifiable data structures which need to be consistent. Window managers. Operating systems. Game engines. Database internals. Most of the things you need to prove are trivial. But you need tools to check that invariant A is maintained by code far distant from where invariant A is defined. Maintenance programmers will miss that.
[1] http://www.animats.com/papers/verifier/verifiermanual.pdf
C/C++ has too much undefined behavior. Ada died off. The scripting languages don't need it as much. Rust had potential for proof work, but went off in a different direction. There are modern proof systems, but they're rarely integrated with the programming language.
On the verification side, it's never had more users that I'm aware of. SPARK and Frama-C are very active compared to almost non-existent use of formal methods in industry decades ago. Rust could similarly have a subset integrated with Why3 platform to make the formal methods easier to use. Further, I've seen extraction done from Coq to C and Rust. There's also one person modeling C in WhyML to write the algorithms in the latter but extract to former. Or something like that. Could be done for Rust, too.
Which direction is that?
For some reason, the moment you bring up mathematical thinking, most programmers shy away and claim that this isn't something they should work with 'everyday'.
I never studied CS and I deeply regret that now. I want to up my game and I don't want to always just patch stuff around to infinity, but I honestly have no idea where to start.
http://infohost.nmt.edu/~al/cseet-paper.html
https://pdfs.semanticscholar.org/12d5/23e586ffde5cbe020cb3fa...
(Second link has a table and description showing the results they got. Stavely's book distills it into lightweight, less-processy form.)
Design by Contract itself is like assertions on steroids. If your language lacks support, you can build it into your functions at beginning, middle and end. If OOP language, you might use constructors and destructors. If trying to understand it, I have a link that you can give even to project managers.
https://www.win.tue.nl/~wstomv/edu/2ip30/references/design-b...
One benefit of making it a formal spec is you can generate tests directly from your specs. This is an old, old technique being rediscovered recently. Various names include specification-based, model-based, contract-based, and property-based test generation. The last thing you can do is manually or automatically convert your specs into runtime checks for the above and/or fuzz testing. The failure takes you exactly to the property that failed if it was one of them.
Finally, for just the most critical things, you can try formal proof on them. SPARK Ada is a great example used in industry with the book being pretty easy to follow.
https://www.amazon.com/Building-High-Integrity-Applications-...
The nice thing about that toolset, esp the proprietary version, is that you can use automated provers to avoid having to do mathematical proof by hand. If something doesn't pass, you have several options: do some manual work on hints to the automated provers or actual proofs in a proof assistant; monkey around with the code to see if different structure or algorithm gets it through; put in runtime checks for just the properties you couldn't prove. If you do the last one and keep programming while solvers run, then the productivity is similar to Design-by-Contract with the extra benefit some properties might hold in all cases. You might also get performance boost by reducing unnecessary, safety checks via proofs that were successful.
What's so wrong with functional languages? I am sure you have heard this cliche a lot but here it comes once more -- I became a much better programmer once I learned an FP language.
Still, back in my Java days I achieved this with a ton of defensive coding, always doing deep cloning before passing complex data structures to anywhere, and trying to enforce design by contract (interfaces and their implementation classes)... which are practically the patterns that any average FP language uses: pattern-matching, immutability and always copying data and thus never passing stuff by reference (always by value), and behaviours / protocols / macros (of the manipulating the AST kind, not in the way C does it).
So to be fair, you are bound to land at an FP language eventually. Maybe you just don't know it yet. Which is fine, learning is about the journey and not the destination anyway.
It can be quite a bit of work but the pay-off can not be over-estimated.
Exactly. Where invariants pay off is maintenance. The original programmer intent has been forgotten and is not visible in the code.
I know a big project which hit this wall. There's delicate C++ code with internal inconsistency bugs, and the company can't fix them.
Testcases can supply this function, as well as counters set up for that purpose (statsd or something to that effect).
Once you have enough of those you can (slowly) start to make changes to observe the effects, and once you understand the codebase add more invariants that you have now determined should exist.
The last project where I took that approach (about 4 years ago now) went from 'intractable' to 'stable' in a relatively short time but it required a lot of thinking and some really hard work to get it there.
Much better if your language/platform supports that sort of thing out of the box, even better if it can be done across subsystems.
I am a big proponent and a fan of gradual refactoring -- even if you simply add a feature that can be forced in (which I never do).
But I am always to open learn some more techniques. And I have to admit with a heavy heart that I never really studied computer science... :(
(Planning to fix that but still have no idea where to even start.)
Is there a "better" answer than worse is better?
Consultants of this type can not afford to be passive, because they are being paid, in part, to push pass obstacles, including political obstacles, and implement an architecture as close to idea as possible.
And the real issue is time vs result. That's the essence of worse is better. It's the well documented fact of diminishing return and exponential cost of additional quality.
You can deliver N features over a given fixed time. Given the urve of quality vs time, there is a true sweet spot where your maximize value, for whatever criteria you want for the value. Spending too much time on fewer items or too few time on too many will respectively waste time on unnecessary polish and deliver stoo many items of no value.
There is a sweet spot.
There is, but it definitely is NOT at one of the extreme ends of the curve where experienced bean-counters will negotiate down the engineering effort (and thus money) to the absolutely minimum necessary for the project not to implode 2 days after release.
Truth is, at one point in your career you have to start pushing back against those bean-counters. They will never get tired, and they are everywhere. At certain point you take a stand, put your foot down and say:
"No, this will NOT be done in 2 days. It will be done in 5 and thus it won't have to be patched 10 times in the space of a week. If you don't like it, my resignation is ready."
You would be surprised how often that works. Many of the business types and managers are bullies only because nobody ever fought back.
...Or you could take a more diplomatic, but still firm, stance. Like "the overall cost of this feature will be much lower if I work on this for 5 days instead of 2". But IMO that almost never flies so I became blunt with time and I simply don't care. I passed five job offers lately for similar reasons and I couldn't be happier about it.
That way, I‘ll write exploratory code different than a prototype, which again is different to a protoduction test, a small production system I‘ll maintain myself, a large production system with different teams and software I‘ll completely hand over or open source as a library.
Only an experienced engineer will realize that each of those versions of the same functionality will be „right“ in the context of their creation.
But if I have a business problem with a small enough epsilon you might not get sufficiently close with your worse techniques in a reasonable amount of time. And to stretch the metaphor even more you may hit an asymphtote and never supply a solution.
Doing something "right" isn't necessarily always slower. Sometimes it is the only path to an acceptable solution.
That's a red herring.
People working on a business program don't need to encode the "whole information to do it right" (e.g. for the eventual version of the program when every constraint is known).
Just the ones that have to hold at the time they right it, and they already know those -- from their current requirements.
>or phrased differently: If I took enough time to do it right, someone else would have already done it wrong and moved on.
That's also a red herring, unless you don't write tests either.
You mean "oracles" (from the blog post). Just program correctly amirite? eyeroll
If your example doesn't deal with user input, you're talking about a problem of modeling under known conditions, which is trivial and ivory tower arrogance.
I don't see the reason for the eyeroll.
You'd have a point if the "just program correctly" meant "just get it right".
But it's not. It's "just use contracts and invariants explicitly defined in your program, Eiffel style to check its correctness".
Which is even more powerful than writing tests.
>f your example doesn't deal with user input, you're talking about a problem of modeling under known conditions, which is trivial and ivory tower arrogance.
Not sure how tests are anything other than "modeling under known conditions". Are the assertions in your test in any way "unknown"?
If you mean fuzzing, you can do that trivially with Eiffel style programs as well.
And the "tests" you do that way are there in the code, available in the debugger, and so on.
As for contracts, basically 99% of the languages have some form of the Java interfaces, or Elixir behaviours/protocols, or LISP's several ways of doing it. But for invariants, I would appreciate an example if you are willing to provide one.
Worse is Worse (Jim Waldo)
https://www.jwz.org/doc/worse-is-better.html
(Be sure to copy-paste to avoid jwz's HN referer-trap)
This line also appears just before that paragraph:
> Of course, worse is better is a much catchier slogan than better depends on your goodness metric
Ultimately, this seems to be applicable even to this discussion, where one goodness metric is "correctness" and another goodness metric is "expediency".
In the original essay, it's simplicity of implementation rather than expediency, but I'm not sure that's all that huge a conceptual difference here (other than for the purposes of a slippery slope argument).
Where it starts to go badly off the rails is when there's a company culture of worse is better and one quickfix, bandaid solution is piled on top of another.
They then wind up with one or more Leaning Towers of Pisa made up of bandaids, hacks, and quick fixes, and everyone running around like headless chickens putting out fires and trying to bandaid all the failures as the towers are constantly in the process of collapsing.
This leads to an ever widening spiral of hacks upon hacks upon hacks as company culture, lack of manpower, and pennypinching never gives them the luxry of doing it right, and cutting the gordian knot by scrapping everything and doing it right from the start becomes ever more impractical.
The dirty "silos" outnumber the clean by far.
However I was still always bothered by mutation. Everything was fine as long as you didn't change any data structures, but as soon as you added mutation to the mix everything fell apart. You could state an invariant, but if you shared a reference to an internal structure then you had to trust everything else in the system not to change anything.
Then I discovered functional programming in the shape of Haskell. Its still not perfect, but it's fundamentally better than OO.
This is guaranteed to fail. What are you going to prove by your mathematical proof performed mechanically? That the program performs correctly? How do you define "correctly"? At bottom, it is defined by an informal specification in peoples' heads. You cannot mathematically prove correspondence to that, even in principle.
At best, you can prove correspondence to the most-high-level formal specification. But how do you prove that that specification is "what the program should do"?
The next problem with this approach is that it has costs. Having to write a mathematically rigorous formal specification for all the behaviors of a program takes non-trivial time and effort. As others have said, that effort could have been put into other things, like more features. Would we rather have more perfect software, or more feature-rich software? Above a certain level of quality, we'd rather have more features. (Yes, software often drops below that level of quality...)
The question of 'what the program should do' is not a mathematical one; it's a philosophical one in the most general sense, and most likely a business one.
With the addition of contracts, C++ will natively support this style of programming without ASSERT macros.
And the evidence is that people write working, even reliable software without Eiffel.
Usually 'working' and 'reliable' get redefined to 'working with what we've tested it with' and 'reliable insofar as our statistics indicate'. Without knowing for sure that you've really covered all your edge cases you're a typo away from some disaster. Fortunately most software isn't that important. But for software that is that important these strategies, even if imposed from the outside rather than embedded in the language will pay off.
However, great (quality) is delivered with those kinds of features and without, and crap software is delivered with those kinds of features and without. And more importantly, I have seen little to no evidence that having those sorts of features actually substantially changes the statistical distribution of crap/quality software, no matter what we feel should be the case.
People can use these safety features or not, and they can use them well or not. Just like they can use non-linguistic safety mechanism, such as really good test-suites...or not.
Elsewhere, he writes:
> This is where I stop understanding how the rest of the world can work at all. And so you probably need to upgrade your understanding.
If the world doesn't conform to your understanding of it, the thing that's lacking is almost certainly your understanding of the world. Because it does work.
I have. Our company has done a fairly large number of studies on the internals of companies producing software and the better companies are at the tech the better they do in the long run.
Note that there is such a thing as 'good enough', and once that bar is cleared I'm fine with cutting a corner here or there to meet a deadline. But I'm not fine with categorically ignoring quality and security in favor of short term wins.
You:
"the better companies are at the tech..."
"categorically ignoring quality and security"
That is about doing something about quality and security, and I agree wholeheartedly.
Me:
"having those sorts of features [in the language]"
That's whether having some specific language features is determinant for doing things. I don't think it is.
When I made that observation in another comment you strongly disagreed with me.
Most businesses put their data in a DBMS, so you have integrity constraints "to ensure database consistency with the business rules or, in other words, faithful representation of the conceptual model of reality."[4] The relational model is both complete and a lot easier to understand than using the predicate calculus directly.
The other shortcoming of any language's invariants is that it lives in your source repo. As coders, we often forget that your production data represents contracts with customers, and you have to take account of the real data when migrating your business rules. That's why the M is in DBMS.
More directly answering the question, most languages can employ property tests [1][2][3] that, very closely to how Eiffel does it, allow you to specify the precise invariant and validate it under randomly generated tests.
But, honestly, a great deal of code, even math heavy code, doesn't have nice general invariants. Real functions dealing with business logic and bugs are piecewise and messy.
And then that only covers the handful of functionality that is even remotely expressible in mathematical form. You still have the user interface to deal with, dependency management, your entire deployment story, and all the problem extant between chair and keyboard.
Technology can't substitute for the grunt work of testing, testing, actually using your system and talking to your customers.
[1]: https://hackage.haskell.org/package/QuickCheck [2]: https://hypothesis.readthedocs.io/en/latest/ [3]: https://github.com/HypothesisWorks/hypothesis-java [4]: http://www.dbdebunk.com/2017/06/what-meaning-means-business-...
At the edges, the invariants are going to be messy, but it would seem like this gives you ample excuse to define functions with strong, narrow invariants as the core of your application, with input transformation functions at the edges.
Provable correctness is one technique in software development, it's not the only technique nor even the most important technique nor even a required technique.
Provable correctness can be useful iff you have a formal specification, and iff that formal specification is more likely to be a correct reflection of the requirements than the code + some tests.
While there are times when that's the case, those are rare.
I could imagine this being implemented in other languages by hooking into statement execution much like a profiler or debugger and executing the checks. Does anyone know of such tools for other languages, e.g Python or JS?
Does anyone have real-world experience with this development technique on an actual project in production?
We are like lumberjacks who so love our axes that we refuse to even consider chainsaws. Many of us don't even know they exist, or if we do, think of them as esoteric and nearly magical. And then there's the fellow who says, "I'm too busy chopping down trees to learn use a chainsaw. I've got to get these trees chopped today!" (So learn to use a chainsaw on the weekends maybe? They really aren't that hard.)
I suspect Wirth would not object to codifying pre/post-conditions and invariants per se. But I think he would object to using them as a band-aid around complicated implementations. It's hard to convince yourself that your implementation is correct when the pre/post-conditions and invariants are themselves complicated and hard to understand.
Maybe his language would be more popular if he wasn't such a snob about it.