Are software engineering “best practices” just developer preferences?
floverfelt.org
floverfelt.org
But really, "best" and "right" are highly situational. Any rule of thumb, even the most basic and uncontroversial, has a situation where it doesn't apply. I was part of a discussion on a mailing list years ago, where somebody got flamed harshly when he mentioned using a global variable. He then explained that he was working on an embedded control system for cars and all the variables in that system were global. The team was well aware of the pitfalls of global state and used a combination of documentation, static analysis, custom tooling and elaborate testing to mitigate them. It was a considered design choice that made it possible to develop high-performance, hard-realtime software that could run on very limited hardware.
In the OP example, it seems the senior dev is saying “on my authority”. And sometimes that is enough, especially if the senior dev can give examples of when not following this practice bit them.
But sometimes there is a higher authority, such as “it’s what is recommended in Google’s SRE book”, which is probably good advice if you are building a large SRE team. (Though as you say, not in all situations.)
I think in the worst case, “best practice” can indeed be used to shut down discussions of a leader’s preferences. But you can smell that out by asking for concrete examples, and asking how widely the practice is recommended.
A good “best practice” should be justifiable and explainable.
All that said, sometimes as the senior engineer you need to go with gut feel; “this design smells like it will give us trouble within a year” is the sort of thing I sometimes say. But I think it’s important to be honest that it’s a hunch, not a certainty in these cases, and discuss/weight accordingly.
Are you appealing to the authority of speed? Compilation time? Readability? Functionality?
I dunno, and it often (especially around readability) comes down to the developer's/senior engineers preference.
That's a really great perspective. There are a bunch of times where I have a preference for or against something, but I can't point to a specific example of when that thing was good/bad, or any objective data about it. It's just that my experience suggests to me (via murky pattern matching in my brain) that particular thing will be good or bad.
It's certainly weaker evidence than data or concrete examples, but I think it's still valuable and worthy of consideration.
It’s poetic language that has nothing to do with specific problems.
What people usually mean when it comes to engineering is “be safe, reliable, and correct.”
Security best practices to be safe.
Developer best practices for reliability.
Etc etc
“Best practices” is hand wave-y fluff for “do a good job” and doesn’t need a technical definition.
Make sure you’re secure, reliable, and correct given the engineering context, and odds are you result in a system that also has a lot of specific best practices in place.
Because that's what would happen if someone suggested "best practices smells like a marketing term" in an actual engineering discipline.
My problem is people take a slogan like best practices and copy-paste in every new framework because it’s de facto best practice.
If the business is one of 1,000 todo apps, sure copy paste.
But it’s new hardware best practices are different and we ought to acknowledge that software use case isn’t as uniform as electronics, where Ohms law and material waste are coupled to waste.
Language choice and syntax choice depends on the problem as the team sees it. Avoid buffer overruns, sanitize inputs.
There you have it; software best practices.
If presented on its own, but then, any conclusion presented on its own without supporting context and analysis is the same.
> But really, "best" and "right" are highly situational
A description of a best practice that doesn't provide a sufficiently precise description of the situation to which it applies as a best practice is generally inappropriate, unless it is the conclusion of an analysis of applicable best practices to a certain situation, in which case the scope is specified in framing the analysis.
It is true that lots of things described as best practices for particular situations with supporting rationale and up getting detached from their logic and context and becoming cargo cult best practices.
To identify the best practice for anything, you start by doing a review of all the available practices in the field for a given problem you are working on. Then once you've reviewed the literature you can work out the pros, cons, caveats of each of these tools, and how these considerations affect your particular use case and your expected results. Then after doing that, the best practice out of available options will be readily apparent, or at the very least strongly justified, not by an appeal to authority or popularity or familiarity, but by looking at what the underlying technology actually does and how its relevant or not to your particular task at hand. In the end you will find the very best hammer available out of all the hammers people have made in this field for your particular unique nail.
Just like your design choices have trade-offs, is it important to realize that there's a trade-off between finishing sooner and making a better solution. Diminishing returns are usually very much in play with analysis.
(I would also challenge the notion that every situation has a different "best practice". That's just creating a solution. "Best practices" are usually general advise that is applicable in most situations.)
If it's a bit more important, do a quick Google, but only break out Excel for the comparison tables if the decision is life-changing.
Honestly, the most important thing that professors don't teach and real life does is that sometimes the optimal thing to do is to not do the optimal thing.
Harsh bashing on global variables is such a dumb thing.
Yes, they can be dangerous. Yes, many had problems due to using them. Yes, we should tell beginners to avoid globals.
But there is no reason to ban them altogether. Experienced programmers should utilize them whenever it makes sense (instead of passing down a value of a local one to almost every function [sic]).
When experienced programmers utilize global variables whenever it makes sense, it tends to bite future generations. Windows's GetLastError is a mess (some functions set it on error but don't clear it on success), I'm not sure about POSIX's errno, and when threads were introduced, these variables had to be changed to thread-local state.
Usually.
There is one pattern I keep using in Rails to inject the current_user for the request into the model layer. At the beginning of a request, Thread.current[:current_user] gets set to the current_user. At the end of the request, it's cleared.
For those unfamiliar, each Thread has its own Hash object and [] and []= instance methods to access it. It's a way to create global variables scoped to the current thread. To hide this implementation detail, I wrap this functionality in ApplicationRecord.current_user and ApplicationRecord.current_user= methods so no one accidentally uses :curent_user.
The most common use case for this is to automatically set created_by and updated_by on a model, the same way created_at and updated_at are set.
Cron jobs can do something like ApplicationRecord.current_user = User.cron_user if needed. Ideally, I would set this in a CronTask parent class so current_user is always available in the model layer.
I always document these methods and explain exactly what is happening and why. Abstracting away from the implementation detail mitigates most of the problems with a global variable. Obviously, the Thread.current method does not work at all if you're using an event or actor driven architecture. Rails does a thread (or process) per request, so this works extremely well.
That's not a global variable; that's a thread-scoped variable.
(It's also not (really) mutable. It gets initialized at the start of the scope and gets removed at the end of scope.)
globalvar = new NopImpl()
works fine for testing. If you squint, you can even think of dependency injection frameworks like Dagger as a lot of boilerplate around a global database of instantiations.You can get issues with a singleton being accessed for the first time from multiple threads at once, for example, so you end up with more than one instance being created or a situation where one thread triggers the creation and another accesses before it has been fully initialized, depending on the code.
This approach caused whole classes of problems that affect regular GUIs to simply disappear, and it was the most performant, least buggy UI I've ever written by a country mile.
I'm a big advocate for functional programming but even I have to concede that in some domains, and particularly in some languages, when you're having to manage universal properties those properties are sometimes best placed at a global level.
but even if the prog-lang had specific support for safe(r) globals, it would still just be a global at the lower (higher?) level.
Welcome to Dependency Injection in .Net Core!
"Those who cannot remember the past are condemned to repeat it." -- George Santayana
My standard rebuttal to anti-global dogmatism is "there's only one instance, and never needs to be more. If/when we do, we can consider doing something else."
Everyone should write Embedded at least once. It's a completely different world.
It really inverts some priorities (I mean development priorities, not the priority inversion on mars pathfinder)
I'm of the mindset where an organization needs to agree to specific principles that everyone adheres. Not dogmatically but pragmatically.
Having that shared "best practice" makes is easier to support other people code/system, allows people to get up to speed faster and as a bonus, allows you to make a blog post on Medium where you can call yourself a thought leader.
Agreed. But GP was talking about context dependency of those best practices. E.g. what might be a good best practice for a large organization inside a FAANG might be very bad for others. Some organization have very immediate feedback cycles. A significant problem in Amazon's online shop will probably show up immediately in sales numbers. A significant problem in the control software of a plane, might kill a few hundred people in a few years before people realize there is a problem. Therefore you cannot a/b test which auto pilot works better in a certain situation. (Although Tesla might disagree about that /s).
The point is every so called "best practice" should state under which precondition it is supposed to be applied. And most blog articles and books ignore that completely.
I think a professional should be aware why a best practise exists and how to deal with a situation where for some reason it cannot be applied as you showed with the embedded example.
Don't forget however that many devs are against best practises out of lazyness or because they don't understand the reasons why they are best pracises.
The overarching problem is that yes, there is software engineering going on in the world, but most organizations are not willing to do engineering. I don't blame the technical staff - they often have good intentions - but rather the typical business is not willing to pay the cost in time or money to do long-lasting engineering practices. This is one of the things not enough of us think about in our career choices - am I going to a place that practices fire drills or engineering?
This results in programmers no longer being able to iterate fast and having to rely on some third-party whose tradeoffs they don't understand, resulting in slow, bloated software and dissatisfied programmers.
Because if so, yeah. You are responsible for the software you write and the dependecies you use. Software engineering is one of the least responsible engineering diciplines anyways. I am e.g. also a certified electrical engineer and of course I am responsible if my wrong decisions kill someone. If I would use a cheap chinese knockoff circuit breaker (because we can iterate faster if the stuff isn't expensive and certified) and someone gets killed, I go to jail. If someone gets killed and I can proof that I followed the currently agreed on state of technology my ass is covered. Of course you can get a lightbulb to light up without following any rule (and maybe this would be more efficient), but in EE the existing rules came as a consequence of deaths and rhe prevention of those is worth it.
In software engineering the worst that can usually happen (unless you work in IOT or industrial applications) is that you loose your user data. Many software devs don't care about whether they loose their users data and there are no tangible consequences. "Oh it was a software error" is still a good excuse, as if there was nothing which could have prevented that software error. I program software myself but I am al for stricter consequences in our profession because it would straighten out some heads who think this is all just fun and games for their personal joy.
https://www.theguardian.com/business/2018/jun/06/timeline-of...
The thing, is there is seemingly no appetite to try to prove correctness of even single machines systems. Let alone distributed systems. I wonder if ever there will be a time where this kind of proof is cheap enough to be acceptable to business.
I’ve seen the other way around too - senior developers rejecting or pushing changes that they find convenient. IME it’s not to do with experience, rather stubbornness.
We call ourselves software developers in Canada.
According to Canadian engineering[1]: The "practice of engineering" means any act of planning, designing, composing, evaluating, advising, reporting, directing or supervising, or managing any of the foregoing, that requires the application of engineering principles, and that concerns the safeguarding of life, health, property, economic interests, the public welfare, or the environment.
To be considered a work of engineering, then, that a piece of software (or a software-intensive system) must meet two conditions:
1. The development of the software has required “the application of a systematic, disciplined, quantifiable approach to the development, operation, and maintenance of software.”
2. There is a reasonable expectation that failure or inappropriate functioning of the system would result in harm to life, health, property, economic interests, the public welfare, or the environment
[1] - https://engineerscanada.ca/news-and-events/news/when-softwar...
https://www.oiq.qc.ca/en/media/pressReleases/Pages/default.a...
INAL; it seems, to me, difficult to enforce. You're not allowed to call yourself an engineer but you can still practice as one as long as you call yourself a developer. What's the difference? In practice... very little.
Most developers I know do all the things professional engineers do.
Unless the government wants to step in and say that you're not allowed to release software without a professional software engineer at the helm I think it's trivial. Unless a company pays the insurance of an engineer and faces severe penalties for disregarding their direction I don't see the point of hiring a professional software engineer. Companies will simply hire developers rather than deal with trifling matters like liability.
And we'll continue to see avoidable security breaches in the wild for ever and onward because of it. The financial incentives are behind "move fast and break things," rather than "protect the public interest."
(Mind you I think we should have more of the latter and I'm all for liability for the things we create as long as we're in control of our future... I'll take the exam if I can be brought in with my 20+ years of experience)
"Microsoft Corporation announced in May 2001 its intention to stop using the term engineer in Canada in the title Microsoft Certified System Engineers - MCSE."
Going against the individual professionals for using the tittle might have been harder. Some are probably real engineers or have received the certification but don't necessarily advertise themselves as engineers...
Where this falls apart is that "Software Engineering" is a real discipline recognized by the organization that handles engineering programs in Canada, however there are no "reserved tasks" so a lot of Software Developers have a Software Engineering degree but can't call themselves that because they (rightfully in my opinion but still) refuse to pay the annual membership fees (about 600$) since their professional order is actually not equipped to audit software engineering work.
Hopefully that helps a little.
It's bit like... being able to practice law as long as you don't call yourself a lawyer. You're a legal assistant instead. In a similar fashion developers are practising software engineering without calling themselves, "engineers."
I don't think we all need to be licensed in order to work -- but companies should be required to hire X number of licensed engineers per Y number of developers. They should be required to pay for the liability insurance to hire those licensed engineers. And there should be repercussions if the company goes against the engineers' direction.
I am not a lawyer (mech engineer), but that's the message that the OIQ has been sending lately. It's unclear when and how they plan to start applying these new regulations.
Any of them can be Software Engineers or not, because we call Software Engineers to the ones with the university career finished
Error: cycle detected. ^__^
Software is by its very nature systematic and quantifiable. Is the quibble with whether programmers are disciplined?
All software companies would meet the "failure or inappropriate functioning of the system would result in harm to … economic interests" criterion.
Define this word without using the word.
Lift: British English. A machine that lifts peo... damnit!
In Canada, I studied in a mechanical engineering technology program that lead to an engineering degree if you stayed on for 4 years. It was hammered into us that we weren't engineers until after you graduated and went through the professional licensing process.
In Canada there is a way to become a P.Eng. in software engineering (and until 2018 in the US there was the P.E. in software engineering), so there is a way for someone who wants to be called a software engineer to legally obtain it. So why is there so much resistance?
You would much rather be recognized as the person who devises the plumbing system for a building rather than just being a "plumber".
Because they aren't going through the process the word and the recognition can't be that valuable.
I feel there is a contradiction in here somewhere that I can't reconcile.
Not to toot my own horn, but I cruised through the FE and PE exams, but those exams filter out lots of people. Do you really want engineers who are incapable of performing simple calculations? The exams represent a minimum level of competence, and they shouldn't be difficult if you stayed awake in college.
Some jobs require you to be a member, but most of these jobs aren't in software.
So most software people I know just use adjacent titles like "developer" or "designer". It's essentially the same job - just without all the extra responsibility.
The word "engineer" has a certain social clout to it, though. Hard for your mom to brag to her friends if your title is "developer".
There are engineers who end up moving to software for just this reason.
Software is super important and becomes more so over time. I'm not sure why being proud of being a developer isn't enough and why it has to end up with wanting to use the term engineer.
I agree it's mostly BS and doesn't make much sense, but I could say the same for much of reality...
Because,
1) a PE license is useless for software/computer engineering.
2) the FE exam covers a bunch of irrelevant material.
3) once you pass the FE exam, there's no real mechanism to advance because there are no apprenticeships available in computer engineering. And you can't take the PE exam without the apprenticeship.
My college spent a lot of money getting an ABET accreditation for their CS/CE programs. As such, they pushed students really, really, really hard to take the FE exam. I went down the path to getting it and realized those aforementioned points. The study guide covered electronics theory that I had no idea about. It also covered silicon chemistry, which was only briefly covered at very high levels.
So I'd be learning pretty complex topics on my own, which have no professional value. Then, if I wanted to take the PE exam, I'd have to find a job where I could apprentice for four years. And, as we know, sticking with a job that long is terrible for your lifetime earnings.
So yeah, PEs are never going to be a thing in software unless they fundamentally change how engineers are licensed. Maybe if it was like nursing or law school where there's a big exam afterwards that you can take, and if you pass, you're licensed. But as it stands now, four years of apprenticeship after 4-5 years of schooling is ridiculous.
Similarly, PE licenses would be so hugely worth it to the industry if it saved everyone time in "technical interviews", both interviewees and interviewers alike. How many collective labor hours as an industry are we wasting annually on "technical interviews"? For most classic Civil Engineering firms the "technical" part of the interview is almost entirely "Is your PE license valid and up to date?" "Yes." "Great, you're hired." The software industry would rather waste multiple hours (if not entire days) of wages of everyone involved instead, and it's rather sad when you think about it.
In my experience no-one cares who's "junior" or "senior" day-to-day, and no-one can compare levels across multiple companies, and that's good for the industry; I've worked with plenty of "juniors" who were better than corresponding "seniors", standardising and formalising some years-of-experience metric would make the industry much less meritocratic.
> Similarly, PE licenses would be so hugely worth it to the industry if it saved everyone time in "technical interviews", both interviewees and interviewers alike. How many collective labor hours as an industry are we wasting annually on "technical interviews"? For most classic Civil Engineering firms the "technical" part of the interview is almost entirely "Is your PE license valid and up to date?" "Yes." "Great, you're hired." The software industry would rather waste multiple hours (if not entire days) of wages of everyone involved instead, and it's rather sad when you think about it.
I've yet to find any software-related qualification that wasn't an active negative. I've worked in a place that applied the acknowledged "best practices" of 10 years ago and it was a terrible environment for producing good code.
Undergrad covers irrelevant material such as humanities, social sciences, and communication that add cost and time to an education. Or at least that's the argument people enrolled in computer science majors where I graduated put forth.
Again, the American perspective is useful. I had no idea you would be bound to one employer during the apprenticeship process. In Canada, employees are free to move around.
I think you can here as well, but the problem is finding an apprentice program in Computer & Electrical engineering is next to impossible. My school had one option for people looking for an apprenticeship. It might be better elsewhere in the country.
Why? Even here Stanford isn't even ABET and nobody seems to care.
If you work on the software in a self driving system in a car, that makes you an engineer. If you're working on software for a space satellite with no occupants... that's not an engineer?
Lots of people in other engineering disciplines build stuff with less rigor than is used to build software. Maybe load test it in Fusion 360 before sending the file to be milled. And lots of software companies test their stuff quite rigorously.
People who write software have imposter syndrome. Other disciplines are not building things better than we do. For every Google there's a Ford, and for every scrappy startup there's a scrappy machine shop.
We are the actual Engineers. For US-Based IT workers, that means a degree from an ABET [1] backed institution with a traditional undergrad and graduate programs.
Anyone else calling themselves an "engineer" while doing IT work are not.
In addition: Readers need to remember this isn't reddit and downvoting comments with facts you do not like is not appropriate for Hacker News. It's is depressing this reminder needs to be added here for facts as it appears a few readers here have forgotten already.
The fact that most users here are reaching to downvote literally the fact that leading Engineering institutions all fall in this bucket is absolutely depressing from this community. It's clear some feelings have been "hurt" here by other users having higher educations.
"Like the CS department, the EE department is no longer ABET accredited. While such accreditation is useful in certain disciplines such as civil engineering, it has no practical significance whatsoever in computer science."
https://cs.stanford.edu/degrees/undergrad/Considering.shtml
Similarly, UC Berkeley also declined to renew their ABET acreditation for their EECS department, and so they haven't been ABET-accredited for the past few years.
"Both of these programs are accredited by ABET through September 30, 2019, but because we have decided not to continue applying for ABET accreditation, we will be developing a single set of student learning outcomes for our department, rather than using the two sets of outcomes mandated by ABET for EECS departments. "
https://eecs.berkeley.edu/academics/undergraduate/eecs-bs/ob...
I am a graduate of such a school and it is a pain to even use that (earned and legally awarded) title in an international context because countries only recognise their own schools. Even in the EU, with its standardized EU-wide titles, you still can't use the "local" title of another country. Even if both titles are accredited to the same EU-title.
It's all status games and protectionism. And it's a silly war to fight, because no one thinks a "software engineer" is an accredited engineer anymore anyway.
You are not an engineer if you did not flow through an ABET institution. You're a developer, nothing wrong with that but you're not an Engineer. No, I do not care if your company has other certain titles, those are easily made up and have no academic backing.
This behavior we're seeing here is the same as if I pretended I was an MD after taking a first-aid-class. It's disrespectful to those that put in the effort to expand our academic understandings and our capabilities for others to turn around and then pretend that title is their own.
It is not.
For new grads? In my experience, they're usually miles behind an 18 year old who has been messing around in their spare time for a few years. There are, of course, exceptions, but at this point seeing something they don't teach at the local universities is more eye-catching on a resume than most degrees.
It usually means they bothered to learn something on their own.
You might be surprised to know that it actually does matter, and it matters in a way that depresses American software engineer salaries: work visas.
The fact that the US government considers "software engineering" to be equal to "civil engineering" means that the TN visa (since we're talking about Canada) applies to people qualified to be employed as software engineers in the US.
As such, this visa allows tens of thousands of equally-qualified software engineers from Canada to compete for a good proportion of the same jobs thereby depressing American wages; why wouldn't an American software engineer (or a Canadian P.Eng who wants to make a business but can't afford the better engineers) be opposed to the weak American definition being the only one that really matters?
(https://www.nafsa.org/_/file/_/amresource/8cfr2146.htm was linked from state.gov)
So, I never took a single engineering class, have no engineering cert, don’t know much about the ethos, and barely even know the definition without looking it up. But I’m supposed to not rock the boat, and claim to be one, like I accidentally became an engineer in the course of designing, planning, fortifying, testing, and measuring software? Like Daniel-san accidentally became a karate master by waxing cars?
Sorry, no. Our “engineering” is just another partially applicable metaphor for what software devs do. But software development is its own set of disciplines. It’s wonderful to pull helpful concepts from other disciplines, but I draw the line at coopting the whole designation.
Current home wiring requires you put wires in the wall at (I think) between 10 and 20 cm from the border, and a small number of cm inside the wall. This means you only have to check that zone, and can use detectors, to find the wires.
My home is from the 1950's. Some wires go diagonally from top left to bottom right at the other side of the wall. We had great fun finding out where they were hiding.
Even if the new wires waste a lot more wiring and PVC tube, I vastly prefer them when redecorating or drilling holes.
I think "best practices" strikes a good balance between things that are personal preferences and things that are laws.
From what I've seen, every company has a different idea of what _best practices_ are. Generally comes down to what some influential developer likes.
And that's fine. "Best practices" don't necessarily need to be universal in scope. Read the Knowledge Management literature and you'll see plenty of discussion of the idea of scoping "best practices" to in terms of "site best practice", "company best practice", "industry best practice" and so on.
There's also a lot of discussion about using different language other than "best practice" exactly to acknowledge that "best practices" aren't always BEST practices, if you get what I mean. Calling them something like "recommended practices" or "proven practices" or similar lingo gives a way to denote things that are recommended at least locally, without having to claim that they are either universal in scope, or absolutely "best" in any sense.
The point of the examples I gave (and a lot of browsing HackerNews) seems to suggest that 95% of the profession is not on board with our most basic practices around unit testing, version control, etc.
It's for people who aren't confident enough to admit to simply having a preference, or knowledgeable enough to be able to explain it
As a freelancer jumping projects, I can't help but see parallels, in that you've really got to study code bases wrt the time of authorship to understand their particular idiosyncrasies.
In the 2010's, people believed in "REST" without considering the context in which these concepts were introduced (eg thin browser UIs, or generalizations thereof as a baseline). Customers, even highly capable devs, flaunt their REST best practices, yet see HATEOAS as optional and pretentious, failing to see the entire point of loose coupling and discovery, and engaging in zealotry about squeezing parameters into URLs instead. Or pretend to, to stop pointless discussions with mediocre, bureaucratic peers.
"Hey why are you having a try-catch there, it seems like it's just gonna break our stack trace and we don't even graciously recover from it" - it's best practice
"Hey why are you using model/view/controller folders?" - it's best practice
"Why are you building microservices?" - best practice.
I got out of a code base with stylecop's settings set to max and treated as errors. Trailing white spaces, mandatory comments on everything, etc. The only exceptions are file size and method size. Files are often in the thousands of lines, and methods can reach that as well. 10 levels of nested if/else. So we're in an unmanageable code base, but at least we don't have trailing white spaces.
Most of the time it could be replaced by "tradition", "pattern", or "the way I've seen others do". If it's a tradition and most people agree to it, fine, might help with readability. If it's pattern, fine, tell me why it's applicable and helpful in our context. If you can't actually explain why you're doing something, maybe rethink it and educate yourself on the topic
SOLID is especially funny because majority of developers doesn't understand / can explain it, let alone have read papers e.g [0],
except maybe S letter, yet everybody acts like they do SOLID*.
Or Clean Code's small function craziness or misinterpretation and going into "avoid comments" approach
* - unless you ask for details
[0] - https://www.cs.cmu.edu/~wing/publications/LiskovWing94.pdf
It's useful to tell someone: "you should have that thing in another class because it's clearly another responsibility", and have a debate on the responsibility itself ; or even on the merits of having a single responsibility per class.
What is not useful is when someone will start making monofunction classes that are 10 lines long on the hotel of "smaller functions are better" and sticking to that because "it's a best practice" with no better argument.
Basically my point is: if you understand what you are doing, great, use vocab all you want. But don't use it as a justification.
Lots of people in software use lots of marketing terms as descriptions of the practice of their work. This is the crux of this conversation, actually: that absent "best practices" rooted in enforced standards, they're all really just marketing terms until proven otherwise.
There's always an evolution of these methodologies and I often feel like in practice they're just a way to mix things up and make code health feel more interesting to those involved. Often people know there are problems with the design of their system, but they can't get buy in to fix them. These methodologies provide some authoritative justification for refactoring work.
> Most of the time it could be replaced by "tradition", "pattern", or "the way I've seen others do".
The most common valid / defensible case I've seen it used is when a person fully understands the "why" in depth, and have formed that understanding on the basis of experience (not blind following or "tradition"), but doesn't have time to deliver a long in-depth explanation every time they do a code-review.
That's not to say it isn't still "developer preferences": there are multiple "best-practice" approaches out there and some even contradict eachother. But I strongly believe that even many of the very subjective, hotly-debated approaches are valid and useful in certain contexts.
e.g. I personally lean toward a pseudo-FP style of programming and am growing less and less enamoured with OO patterns for various reasons. But OO is still a useful abstraction, and if you're doing OO, I've found something like SOLID to contain a great deal of wisdom. I never sat down and decided to do things "the SOLID way", and learned that. Rather I wrote a lot of bad OO, ran into problems, gained insight from experience, and later stumbled across SOLID and found the pitfalls it mitigates familiar.
A sibling commenter has the following quote, which I agree with:
> SOLID is especially funny because majority of developers doesn't understand / can explain it, let alone have read papers
I think this is exactly why the term "best-practice" is so popular. I would not have understood SOLID in any depth if I had come to it fresh: I needed to learn SOLID informally by accident, internalise the challenges it's designed to overcome, and then recognise that intuitively from my experience when reading about SOLID later.
That's not a level of understanding you can typically impart easily in a conversation when suggesting someone do something differently. It's much easier to just say "best-practice".
This paragraph highlights something I've been saying for ages.
Most criticism of Java needs to be directed towards Java programmers and not the language itself.
The language allows you to simply make a class. You're not required to make an interface and then make a class that implements it, and yet, Java programmers do it anyways and then criticize the language for being verbose.
Getters and Setters? You probably don't need them. Classes can have public member variables.
Java programmers seem to have the hardest time understanding YAGNI.
The getter / setter debate and public fields is about exposing the internal implementation of the object (and thus making it unchangeable without breaking other code) and being able to reason about where the internals are used (if you do need to change them).
For example, if I've got a java.util.Date exposed as a public field and someone uses it, I can't change that later to a java.time.LocalDateTime unless I change all of the things using it. If this is a library that others are using it may mean a cascade of unknown changes.
If, on the other hand, the Date was exposed as a public Date getDate() { return date.clone(); } then I don't have to worry about it. When the internals are changed to LocalDateTime, then Date getDate() { return Date.from(local.atZone(ZoneId.systemDefault()).toInstant()); } and everything will still work.
I don't have an issue with the infrequently used "default package private" level of field visibility where only classes in the same package can see that field as that limits the range of the changes to the classes within single package (in a single project).
https://blogs.oracle.com/javamagazine/post/records-come-to-j... and https://dzone.com/articles/what-are-java-records
I'm really looking forward to using the local records defined mid stream for bundling the information to the next part.
Only retrieved? `final` and set the fields through the constructor.
Sure someone could implement setters-only if they wanted that. Except I’ve never seen it and get/set are always used instead. Just one layer of indirection for no benefit.
Consider a collection class which has a size field. `final` would be the wrong thing to use. If you expose the size field but make it final, well, it's immutable and your entire collection is either lying or also immutable. If you expose the size field but it's not final, then anything can alter it. Consequently, a getter (the concept of one at least, see C# again for a cleaner approach than what Java did historically) is useful and then when another element of the interface is used (adding or removing elements) the size field can be updated appropriately. The next time it's retrieved, it's correct and you don't need to recompute it.
This kind of thing can be a consequence of many other systems, a collection is just sufficiently universally understood that it's a good example of the concept.
But then again no one calls it a “getter” (not even Java calls it `getSize()`) since the get/set discussion is about updatable fields, not the inner guts of objects.
Has anyone argued against encapsulation? No one has.
It might be good if a change just breaks client code. The client expects just to get/set something: they might not expect that some update migth add arbitrary logging or internal logic (like setting this value will also set another value, but we won’t tell you).
Most of the get/set stuff that I see are for value objects with either no or little business logic. Simple value objects _should_ just expose their implementation.
If that contract is the underlying field implementation, then that means that those fields are frozen and cannot change.
If that contract is instead methods, the underlying field types can change (for example from a Date to a LocalDateTime) while the method contracts remain the same and new method contracts are added to expose more functionality for other clients / application modules.
In particular, this was code written in the Java 1.7 days and it was Date (and all the mess with java.util.Date and java.sql.Date) while in 1.8 java.time was provided which allowed the underlying implementation of the object to cleaned up without changing the contract of the methods (things wanting a Date still get a Date).
Yes, changing from a Date to a Calendar (because of the aforementioned java.sql.Date mess) to a LocalDateTime were significant changes -- but the clients didn't notice because the methods they were using remained consistent.
The deeper you expose the client contract into the guts of the object, the more difficult it is to change when a change is needed.
Now, if you're just passing DTOs around between classes within a single package or local to one library that don't leak - feel free to do whatever is needed. I suspect that records will solve a lot of the boilerplate DTO code, though passing a record outside of a library boundary gives me a bit of unease because it means that changes to the record will be breaking changes to the clients.
That's the 'D' in SOLID -- dependency inversion. An object's dependencies should be defined in terms of abstract interfaces, not concrete classes. The verbosity is just boilerplate, and it would appear in any statically typed language if you're following SOLID principles.
> Getters and Setters? You probably don't need them. Classes can have public member variables.
Getters and setters are part of the JavaBeans spec for being able to load and configure arbitrary beans. If you're writing JavaBeans, as many EJB or Spring application developers are, you'll use getters and setters.
DI does not talk about the interface keyword in Java. It talks about interface as the public surface of an object or system.
Programming to a Java interface declaration does not guarantee the code is depending on higher-level abstractions - this depends on how the interface is defined. An interface which just replicate the public surface of a class (a "header interface") is on the exact same abstraction level as the class, it just introduce needless boilerplate.
On most languages this requires a lot of boilerplate and indirections though.
We do need them if the objects interact with a lot the libraries that we use. Libraries that we didn’t make. They expect get/set.
I agree that getters/setters are very overrated. I tend to make public-final fields when I can. Most of the time I can’t though.
Which is to say, early ecosystems in Java certainly needed this criticism. They did adjust, though.
Instead, it's always some monstrosity held together by inheritance, XML/(awful) Gradle and liberal sprinklings of magical annotations that always (always!) bite you in the backside at runtime rather than at compile time, because why would you prefer to have good tooling that takes advantage of static typing to tell you what might go wrong.
I am appalled by what Spring mentality did to my language.
It was also for a very long time missing some fundamental Stream, List and String processing features. Just getting the contents of a file or converting a string to bytes, or even just initializing an Array often required 2-3 lines of verbose OutputStream(StreamBuilder().fromArray(Arrays.asList(1,2))).readBytes().add(3), wrapped in a try-catch for all the checked exceptions. For things that in C# would just be a oneliner of new List<int>({1,2,3}) or in Python [1,2,3].
This is mostly solved in current versions of the language, but the reputation and the "best practice" design-patterns remains.
I think it's that engineers of physical things have many more hard constraints they have to wrestle with, and software engineers largely don't. Your code doesn't need to obey the rules of gravity and chemistry and materials science, it just needs to somehow accomplish the task.
And you see those best practices in the places of software engineering where there are hard constraints: cryptography. high performance code. realtime systems.
It's not just a senior engineer's opinion whether you should use ruby or C if you're writing the firmware for your race car. If you use md5 to hash user passwords on a major site, you'll be hung from the rafters.
Is it actually anything like civil engineering? To my knowledge chip engineering revolves around yield. There's no such analogous concept in designing buildings that can only be reasonably constructed correctly 70% of the time and attempting to reuse the bad buildings for other projects.
Software engineers:
- cost of components is $0 (use one class or split into 2, there is no cost metric to decide)
- physics don't apply to components (we can't use this doping agent because X or Y. We need to move the factory to an area of low seismic activity to improve yields etc.. etc..)
Basically, physical engineers have so many constraints, solving the problem is the hard part. Software engineers have so few constraints, usually solving the problem is the easy part, and we have time left over to argue about abstract cleanliness concepts like composition vs. inheritance and such.
(Again, this is the rule, the exception is problems like "We need this service to do 2 million requests per second", and there we don't argue about functional vs. OOP, you do anything you can to hit the number)
Most of the industry does easy Engineering and that's what we talk about for the most part. The part of the industry that does hard engineering (the largest orgs, developers of mission critical systems like weapons) keep mostly quiet about how they solve their problems because that's a trade secret or highly classified.
Software engineering as a discipline is dominated by appeals to authority ("Clean Code", "Google does it this way", "Djikstra said so", etc.) without any (or at least not much) attempt to ask why or whether. I think we'll automate away much of software engineering (likely with very poor, inefficient, and buggy implementations) before it matures enough as an industry to be actual engineering. Engineering (and the science behind it for that matter) advances from curiosity and a healthy skepticism, not the rampant ego-driven self-promotion that runs through SE.
I adore the craft-like parts of software dev, wouldn't trade it for anything.
> If a builder constructs a house for a man but does not make it conform to specifications so that a wall then buckles, that builder shall make that wall sound using his own silver.
- Code of Hammurabi, 1755–1750 BC
On the other hand, if the customer finds out that their door is inconvenient and it would be much better to have it a bit to the right, noone expects a house builder to fix that at their expense, you bought what you saw. And the same thing if it turns out that the house is very difficult to maintain because it's inconvenient to get to the piping. And ifthe customer buys a bigger car and the garage needs to be adapted to fit it, that's their expense.
Those three would be the main equivalents of all the commonly seen software "best practices" which generally either refer to feature design, the maintainability of the code, and ensuring compatibility when an integrated system changes.
One day that will extend to everyone like in all industries.
Who can't manage then closes doors, just like bad restaurants after a surprise health check.
All of the stuff engineers argue about and that seem really subjective are the things where you just get very little feedback about who is right or wrong.
(Actually I dare say that sotware itself has no physical constraints at all: software artifacts and software executions do.)
There are, for instance, famous books written about which errors can be proven to be absent in your program and how (vulgo typechecking). There is a huge amount of research about data structures and their internal logic (and at least one, very weird observation about the meaning of the derivatives of data structures). And I don't need to mention complexity theory, do I?
Just because a huge part of the practitioners ignores the scientific base of our discipline doesn't mean it doesn't exist.
The fact that code has an extremely precise semantics comes from it being a formal system. But its close relation with maths and physics, besides that they are all formal systems, is mainly because mathematicians and physicists were the first to create it; it's mostly a matter of tradition. There are ways to create, use and study software that are closer to language studies than they are to math, and those are legitimate comp-sci too. Non-formal aspects of building software, like which style guide to establish in your organization, are part of the discipline even if you don't use math to study them.
Formal proof is a convenient way to check that your detailed, precise assertions are consistent with your initial axioms. This doesn't prove at all that there are no errors in your code, only that there are no contradictions in what you are saying. Your specification could still be wrong, and then you could still be saying the wrong thing in terms of what you intend to say or achieve; and the formalism won't help.
It is not surprising that managers gets to decide how software is built in their department. Software is an explanation of concepts with a particular style, and those who set the tone implant their quirks in it. You're building what the manager tells you to build, and end using the same language.
Software assurance is still a somewhat nebulous process and I'm partly involved in some research around it and proving that a program is logically sound is indeed only a small piece of the pie and hardly gets you anywhere valuable.
FizzBuzz is provably logical, but that doesn't mean you can load FizzBuzz onto a space shuttle and expect it to fly correctly.
How does research in software assurance treats the human side of behaviors and desires, which can't be formalized? Are there protocols that can increase reliability for an established purpose?
There are a number of general Software Assurance protocols. I'm not super familiar with them, but DO-178C is one I hear about often which is a process specifically for assuring/certifying airborne systems.
This took time to achieve. You wouldn't be able to read Newton's papers easily, even though a large amount of high school mathematics is based on things he invented/discovered.
Mechanical engineering has physics as a foundation.
Chemical engineering has chemistry as a foundation.
What is the scientific foundation of software engineering?
I suspect it is a mix of cognitive science, linguistics, and anthropology.
I agree that math describes limitation to computer science and formalisation. But software engineering is more than computation.
Category theory: I suspect that category theory (well, really just abstract algebra) will tend to make software engineers better at writing code. However, on the other hand, the category theory operator soup that sometimes shows up in haskell, et al makes me think that too much and not enough restraint isn't a good thing.
Computational theory: After 14 years of software engineering, I only needed to care about this once. It looks like the answer is try not to make loops inside of loops, use the standard library, know the bare minimum, and if all else fails then find a way to cheat with hardware (graphics cards, simd, massive distributed systems, asci, etc).
Logic: So ... like type checking? Or prolog? I mean, knowing logic is good. But, like, where exactly do you expect the benefits to show up.
Complexity theory: Are you talking computational complexity? If so then I guess my answer for computational theory (also what did you mean by computational theory then? like lambda calculus and turing machines? When does that help?).
Edit: this is a discussion forum. The downvote button is not an agree/disagree button, it's to penalize irrelevant comments. If you'd like to disagree, please reply and state your thinking instead.
Perhaps you don't want to make broad generalizations?
Section 3 gets into the "what is computer science". 3.10 through 3.13 get into the engineering aspect. Section 6.5 puts it into historical context.
Computer Science (more abstract) and Computing Science (less abstract) are branches of Science that have given a foundation to Software Engineering.
The problem is that most of the programming and software development that happens nowadays (and what people pay for) doesn't use it.
I compare it as Chemistry and Alchemy. We are still in the "alchemy" stage of software development. Sure, people who see themselves as "experts" are combining existing stuff to create new things. But there is a few set of experts that use the science expertise to implement systems.
Would love to hear your thoughts on this, esp. the linguistics and anthropology piece.
I agree. Creating a solution that is clear to navigate for future developers is valuable, as is one that is flexible for future modifications. These things depend much more on how humans understand the code than on how machines understand it.
That said, other engineering disciplines aren't entirely bereft of that kind of human aspect either. Take architecture for example. It's critical for a building to handle the forces put on it. But it's also important that humans can use it. Having a good building layout is much more a matter of understanding humans than of understanding physics.
And then there's the whole style thing that architecture has. A building is not always only functional. It can very much be a work of art. And that style is not just decorative. A style can conjure up certain emotions to put people in a certain mindset when dealing with the building. (E.g. putting a modern art museum in a neo-classical building would be dissonant.)
The interesting question is this: would other engineering pursuits (say civil) have just as much chaos and lack of authoritative practices, if changing practices would be equally fast and cheap for them?
"Best practices" in software engineering are usually about internal development processes and don't have any verifiable connection to outcomes.
In other words, we have two entirely different things labeled with the same name. People who commonly use the phrase "best practices" for software are literally trying to confuse you and generally are not worth listening to.
That said, some things in software are worth analyzing to have a better process, but those things need to be examined within a specific context. If someone claims that you need to, say, create an interface for every class, they should be able to explain why and how it is relevant to your work. If people make claims they cannot explain by connecting them to meaningful outcomes, those people are, again, not worth listening to. They might be mindlessly parroting something they have heard without having any clue as to the meaning of the practice. Unfortunately, our field is full of "professionals" that do exactly that.
Software is a pretty messed up domain that is frequently a self-licking ice-cream cone. (You write code to solve problems created by other code.) Because of that, it's often socially mediated, just like non-engineering fields. To establish anything for real in this self-referential environment you need to be able to have conversations about costs, tradeoffs and outcomes - within a specific context.
I agree, following a “best practice” without understanding the “bad practice” that it’s trying to prevent is silly. But just discarding best practices because no one understands the reasons behind is also silly.
I would argue that there is also a lot of value in following team-level best practices even if you do not fully grasp the rationale or understanding "bad practices". For starters, it ensures that the team's work complies with the principle of least surprise and follows a common and standard style, which helps with onboarding and forming a mental model of where and how all things are.
Software Engineers should just say "this is how we like to do things" and not pretend that there's a holy grail of correctness when really it's just what they like.
So what do you do with a "best practice" that doesn't make any sense to you? Do you just keep doing it forever because you can't understand why anybody would invent it in the first place? To take an example I'm familiar with, there's a good chance if you don't understand a Java OOP best practice it's because you've never encountered the problems it was designed to cope with. The OOP design principles that came out of the 1990s and became orthodox in Java around the turn of the century were built to solve the problem of scaling monolithic application development to teams of dozens or hundreds of developers. You would have dozens of people, imperfectly coordinated, hacking on a monolithic codebase for an application that was released quarterly (if that!) and ran on servers that cost more than the CEO's car. The coding style innovations of that era naturally focused on coming up with more and more ways to add layers of protective abstraction, and on training programmers to add those layers to their code no matter what, even if it doesn't seem worth it because 99% of the time, if somebody didn't understand that it was worth it, it was because they were inexperienced and hadn't lived through a horrific integration debacle that delayed the quarterly release by a month.
In my opinion, if your problems don't resemble those turn-of-the-century enterprise monolith problems, then you shouldn't program in turn-of-the-century OOP style, and you should take "best practices" from that era with a huge grain of salt. You should only use them if you can see how your codebase will benefit from them.
Even Java, the bastion of OOP conservatism, is acknowledging that "best practices" are relative by adding record classes. Record classes are first-class language support for violating the best practices that were drilled into generations of Java programmers!
(There are people who do have those turn-of-the-century enterprise monolith problems, for example, library developers! They ship their changes to hundreds or even thousands of people they've never met, who don't keep up with project updates, and who don't budget time to deal with breaking changes. So a lot of the ideas turn out to be really valuable! Just not for, say, small teams building microservices.)
> At the end of the day, you wind up in a lot of fairly pointless arguments about tech stack and coding conventions that 99.9% of the time don’t make a bit of difference to the final product.
That's a great conclusion.
To be honest, "correctly" is whatever actually works. But since we as an industry haven't been around for a long time and don't collectively know what actually works, it is simply the case that we defer to those who have comparatively more experience, so that we may get decent solutions now, as opposed to excellent ones later.
It took the ancient civilizations hundreds if not thousands of years to perfect architecture to a reasonable degree, where it's possible to be fairly certain about the viability of most typical designs, as well as the tradeoffs that nonstandard ones might require.
Personally, i think that we'll only be able to talk about what truly works and what doesn't once the industry cools down - when there are new JS frameworks once a month or once a year as opposed to every day (or for any technology, really). When there are very few breaking framework changes, because the frameworks would finally be stable. When the primitives around doing web development, interfacing with devices and everything else have been distilled to their most usable possible forms. When a developer doesn't need 10 languages or 20 frameworks to do their job, but can instead rely upon a few, after most others would have died off after a sort of singularity of languages.
That's when useful certifications would be possible. That's when estimates wouldn't be guesswork. That's when the education systems could actually prepare people fully for working in the industry. That's when the development of projects wouldn't be such Wild West, but instead would be a process with far higher quality, a true engineering discipline even at the expense of projects taking longer to actually develop, much like you don't construct buildings in an ad hoc fashion.
Now, whether that will happen in a 100 years, a 1000 years or never, is another question entirely.
People wonder about whether they should create their back end in Ruby or PHP. People wonder about whether they should create their front end in Angular or React. People wonder about whether they should use MySQL or PostgreSQL for persistence. They wonder about which of the many OS distributions they should use for hosting their application.
But perhaps that's the true waste of time - maybe we shouldn't need multiple approaches to each problem. Maybe we'd only need one, which could then be the sole focus of the industry. The tooling would be incredible if there would be just one workflow to support. The technologies would be tightly integrated, since that's where all of the effort would go. And there could be models built around the language and frameworks to such a level that any usages of antipatterns could be immediately identified and even fixed automatically.
If you ask me, the millions of man-hours that have been spent on creating a brittle and fragmented landscape of tools that don't work well and make developer's knowledge obsolete in a few years while also urging people to do CV driven development are the real waste of time.
Of course, that's the reality that we live in but maybe for the developers in 500-1000 years it won't be that way.
- extract an interface or not -> an interface can speed up compilation (under the right conditions)
- pass more or less arguments -> how many call sites exist? What’s the performance difference? Would it complicate testing?
- testing -> depends on what you’re building, when do you need it by, and how problematic a bug may be (and more)
The reason it looks like some random preference is because over time we naturally gravitate (or been told to do) what works, and we keep choosing it heuristically since a thorough analysis of the problem is too costly or impossible.
Civil engineering has a bunch of hard rules on have X slack here because people will die for such mistakes. But I suspect you use best practices for less high stake stuff (do we use this outlet configuration or this one?) (actual civil engineers are welcome to correct me)
More or less right about hard rules. They're not truly hard, and it's different in different countries. Some countries have performance based rules, others have descriptive rules (must have 35mm of concrete cover over reinforcement bars) but even in those situations you can usually get some sort of person to overrule the rule, it's just costly in both time and money, but sometimes its worth it.
Take ultra high performance concrete for example. It's almost a different material compared to the normal stuff. But for run of the mill construction everyone kinda likes sticking to the rules because it's like outsourcing handling all the edge-cases. Kinda like using Postgres over writing your own persistence layer.
As for hard rules in software, that would be tough. It's much more multidimensional and maneuverable than civil engineering is and we have less history dealing with it. Also, there are way more security concerns than civil engineering, which is mostly about safety concerns, where there are no arms races against you.
We could still do it abstractly though. Favouring maxims and penalties over nitty gritty rules.
Longer answer: I'm confused by the examples given. Nothing there is a best practice IMO, they are only opinions.
This writer is confusing "use git" or more basically "use version control" with the how's and why's underneath. Everything beyond "use it" is an opinion, with multiple "best" options depending on your desired workflow or requirements.
Same for Java - the senior explained why this version of "best" is best for them, but the real best practice of "define your interface as a contract" is hidden behind these opinions.
Contrast this with the civil engineer used as an example, who might say "use a safety factor of 3x rated weight for all fasteners" as their best practice. Using fasteners rated at 2x is a violation of that, but using screws vs bolts vs adhesive are all opinions and depend on the particulars and preferences of whoever is doing the work.
But, more fundamentally, what the author could have responded to their friend is: "Yes, we do have a code of ethics and professional practice standards[0]. We do have well-researched best practices and a rich standardized body of knowledge we can use[2]. We do have formally adopted standards through IEEE, ISO and IEC[1]."
I do get the sentiment behind the question though and personally wish we were more formally trained and held more rigorously to a professional set of standards. It does diminish the term "Software Engineer" as a engineering field when we use the title so loosely but (on some level) expect the same level of respect, pay and status as other engineers.
[0] https://ethics.acm.org/code-of-ethics/software-engineering-c... [1] https://en.wikipedia.org/wiki/ISO/IEC_JTC_1/SC_7 [2] https://www.computer.org/education/bodies-of-knowledge/softw...
This is the part of the article that made me think this:
>As I type this, I’m in a discussion about whether it’s better to pass a few unnecessary parameters to simplify a bash script’s internal logic or pass fewer parameters and make the bash script more complex.
This sounds like they're on the verge of parameterized, object-capability design - passing in the paths to operate on, rather than hardcoding some internal logic to determine what to do. If you do this in the right places and at the right time, you can do amazing stuff, reuse scripts in totally novel environments and for novel purposes. At other times, it's not necessary. But I'm guessing neither side really knows how to use that to do amazing stuff.
Some programmers don't have the skill to recognize when a specific technique is justified or unjustified. So, unmoored from technical reality, they just argue about cultural norms - blindly copy what someone else did once, which brought someone else success - cargo culting.
That all sounds very mean, but if this is what's actually going on, I'm not sure what the solution is. Maybe more focus on really impressive and amazing concrete projects, rather than just individual practices in isolation?
and then when this does not work, they call themselves artists.
i actually heard this quite a lot in all these years in the field - "coding is an art". it is for some, for most is just copy/paste from SO :)
Given the context of the authors ( and this also includes employment context, socioeconomic and personality factors for everyone involved ), the best practice is something that has been "proved" to work well.
So no, it's not just a preference, but in practical terms many times it's a preference that some people agree it worked ( in their context ).
And let's not even talk about the "best practices" and technologies created just to sell you something. I think by now it's not a secret that most "developer evangelists" or even "famous" developers are just people doing sales and marketing, some of them don't even realize it such is their ego trip.
Professional Engineer is a modern concept. In the United States it started in 1907. Sure we have been building irrigation systems for thousands of years but it wasn't regulated by governments until recent history.
Until then it was a practice guarded by guilds and seen as a craft.
Software isn't without its own history. The mathematicians and logicians had been working on it long before the first computing machine was built. We've known how to compute values for thousands of years.
Are we still in the craft/guild phase of the discipline? I don't think so. There are professional engineering organizations around the world that are certifying software engineers. If that is all that is required you can apply today.
The missing piece is that it's not required by governments around the world to have any professional affiliation or certification to practice programming professionally. Some argue this is a good thing as it keeps the playing field level. Others argue its bad as it enables profit-motivated companies to cut corners that harm businesses and users.
But as far as best practices go, as long as there are enough people practising them across the industry, then it's not simply a preference. A good guide on this is the SWEBOK [0] published by the IEEE which attempts to catalogue these practices in a living document that gets updated as the state of the art develops.
[0] https://en.wikipedia.org/wiki/Software_Engineering_Body_of_K...
I once built a system reverse engineering a program used for soil analysis to see why one of our bridges fell off its suports.
Also you can start a bridge in your garage.
Software can be just as reliable when there is a need for it. Thing is, 99% of the time you don't need those extra 9s.
Maybe in a century techs and standards will stabilize.
It's exactly as old as nuclear engineering.
If it's a toddler, it's because of the mentality of the people involved, not because there was no time to figure things out.
The devs writing code for the next social media app operate under very different standards than the ones writing code for nuclear reactors. And that’s ok.
Not to mention funding for governments that actively sell exploits to other nations. Standards seem to be left up to the industry. I saw the Kubernetes hardening guildelines from NIST a while back that was cool.
SE started out from mathematics, but the hardest problems are not related to it. We're only pretty good at nailing the things directly from mathematics like algorithmic complexity or distributed system guarantees.
Civil engineering best practices are written in blood, but I think software engineering best practices can be stretched to include sweat and tears too.
To truly suggest something as a best practice, you need to understand what it requires from the technical and social environment around it, and when it applies and doesn't apply. We're nowhere near that level of discipline as a field. This lack of discipline is why we wince when we hear that a startup is implementing something like voting machines: we know the financial incentives that lead to startups focusing on speed, and we can imagine the discipline that voting systems require. We know there's a mismatch between the social environment and the likely project management approach. But we're blind to the social and technical requirements that allow other practices to work well. When is it appropriate to use inheritance? Someone will inevitably say, "You shouldn't use it?" Why does it work so well in Rails?
IMO it's how developers like John Carmack[0] and Martin Fowler[1] can make opposite arguments about things like the benefits of having code inline or in functions. These two opinions work in conjunction with their environments; maybe video game and aerospace coding requires budgeted performance requires mutability, so Carmack has to control how you interleave side-effects. Maybe enterprise-grade Java programming doesn't have much of a performance budget at all, or maybe he values isolating testable functions more, so Fowler can take other approaches that allow more "readable" styles and not worry so much about side effects (since there are few).
[0] http://number-none.com/blow/john_carmack_on_inlined_code.htm...
I'm sure there will be howls of "you can't let them put code in the database!"
Why not? It's their (the customer's) database and their web service, after all. You can do all sorts of validation on a form input and a database field (like with Tidy and Bleach in my case with Python). Can't do any on a plain text template file.
But "separation of concerns!"
For who? It's always been bad practice in my opinion to assume that not only do end users have on-staff development, or contract development, but that they have multiple tiers of it which need lines drawn between the duties of each. Who says everyone who needs custom software or custom web services is an IBM-sized conglomerate with multiple departments full of software developers? Why can't a mom and pop restaurant have a nice website and a nice phone app? Because they don't want to learn to use javascript, webpack, npm, git, and an IDE? Is that the only reason why?
The least accessible (in a physical sense) parts of web development are the parts that a customer might do themselves (CSS and HTML). I will not believe there is a good reason for that other than software developers trying to talk themselves into more jobs and more contracts.
Kinda like how storing web templates in files is totally dependent on the people who upload them not putting crypto miners in the linked javascript(s) [1]. Or totally dependent on PAM not having a vulnerability [2]. Or totally dependent on SSH not having a vulnerability [3].
In terms of libraries and utilities I can give PAM and SSH a pass for fixing these things long ago. In the case of restricting a customer's access to the mechanism that renders their thing in favor of the option of "trust this guy who uploads things instead" you've got a much tougher sell about why that's better.
1. https://www.fortinet.com/blog/threat-research/the-growing-tr...
There have been a lot of best practices that have been hypothesized over time: OOP, functional programming, unit testing, generative testing, formal analysis, strict typing, weak typing, etc.
And all these as-of-yet unfounded hypotheses are important! You've got to have a theory of how something works before you can prove that it does. Hopefully we can start to devise those proofs.
Gone are the days when we threw together a php, html, and JavaScript in one file... wait, or is it?
"Some are purely ritual, but some are there so that we can guard this dimension from horrors that live within!"
"Uh, I guess we should at least do the latter?"
"Oh? You can tell the difference? That's great!"
-- Girl Genius
I get the theory, but in practice, the benefits are just theoretical. You could reimplement interfaces for your tests, but it is easier just to use a mocking library.
An example of this I recently experienced was trying to understand and debug what should have been a simple integration app, but where a ton of injected commands and queries were used to implement the functionality. Following the logic was painful as the code was completely atomized for no particular reason. Worse, real-world concerns, like proper logging, were ignored.
I hate to call this an "autism tax", but perhaps there's something to the term: many intelligent developers, especially left unsupervised, tend to pursue highly abstract solutions, to what should be straightforward problems in order to satisfy a compulsion for order and symmetry.
There also really is software engineering that goes on- I work in an org that does extensive analysis, testing, and validation of firmware before it is rolled out. It’s a real thing. That being said, so is cranking out a CRUD web app with zero testing to make our PMs data collection tasks easier. It’s all on a continuum. The key trick for software “engineering” versus just development is knowing where in the continuum a given project needs to be and what tools are appropriate in that context.
Edit: Surprised I haven't seen this mentioned in any other comments. I had thought this was pretty common knowledge, at least amongst people with Java experience.
// A
const int giraffe = 1 + 1 + 1 + 1 + 1;
// B
const int number = 5;
At some moment, you will meet some disagreeable person that will say they are the same and it doesn't matter which one you pick.A is similar to Roman numerals. We all know that Roman numerals are no longer used for most purposes and were replaced by the numeral system we currently use. Not only the new numeral system is more convenient for various reasons but it allowed people to advance math further. So A is better than B in that sense.
Then, A uses an identifier that doesn't represent its value. We can also say it's bad because of that reason.
You can try to seek ways to compare and improve code. Not all of them will be effective, but at least you will be trying. That is better than being that disagreeable, nihilistic guy that thinks that everything is subjective and relative and won't agree with anything you say.
You have to learn how to treat your code with respect and prevent it from becoming a tech debt dumpster.
There is code that is objectively bad. And you will know when you try to maintain, debug or profile it, or when you have to explain it to someone else. Or when it keeps breaking over and over again and many defects are connected with it. Or when it becomes a product limitation and you have to apologize to customers about it.
Personally I think the most important thing is to agree within a project, what style and what practices to follow, so everyone is going in the same direction. This should in my opinion make the code more maintainable and extensible, due to the reduction in cognitive overload for the developers involved.
Where is the difference with software? You get the same kind of constraints and need to build something from libraries and custom code, that fits all of them.
There may be more constraints for a skyscraper than a small garage, and there are more constraints for airplane software than a website. You can't write flight controllers in javascript, the same way you cannot build your airplane out of toilet paper. There are also more constraints for airplane software than for your backyard garage. It only depends on the regulations in the field. Most of the times software doesn't have the potential to harm people, like houses and bridges have. So you have less regulations.
If you want to build a bicycle, there is no right solution either. You could benchmark it by weight, like you could benchmark software by memory usage.
Most engineering products only rely on best practice and the way the company does it since years, from experience. There is no "right" solution, neither in civil-, nor in software-, nor in engineering in general.
There _IS_ data about some of this, but the results frequently go against the opinions of various people, so they are discounted. And then there is the problem that the industry as a whole has a tendency to run away from old/stale/well understood/etc technologies in support of untested new products. Which is how you get the cool language churn. You can just look at the last 20 years of server side web development, php, ruby, python, javascript, were all the "best choice" at one point or another, only to be pushed to the sidelines when they were discovered to be sub-optimal in some way.
So, its like the C/java/etc brace problem. There were a fair number of actual studies showing that matched brace styles seem to result in fewer bugs back in the 1990's, yet overwhelmingly the opensource community rejects that in nearly every single project regardless of language. Why? Presumably its just personal preference going back to the old days of 80x25 tty's where whitespace was at a premium, same as the 80 column limits many projects employ.
It doesn't matter if someone, or a group of people, spent years researching a topic: even given an extremely similar situation with similar resources and constraints, an engineer right out of school will still feel compelled to try and solve the problem anew.
Part of the issue is that we're very bad at identifying constraints and context, and thus it's really hard to apply pre-existing solutions. Eg: people trying to apply concepts developed by large FAANG-style companies in a startup.
Part of it though, is sheer arrogance. Everyone feel like they know better. There's also a bit of "playing programmer" going on: folks do a lot of things because they find them more fun, even if it was somehow objectively a worse solution (and they knew it). Because software engineers are in such high demand, people above are afraid to drop the hammer. Concept such as team or individual autonomy are put above the global maximum of the business. This autonomy and freedom is justified by saying it drives innovation, but you're not innovating if you're constantly starting over. For example, while modern languages do have some cool new features, we also keep reinventing the tooling, editors and debuggers around them, which drives progress in those areas to a crawl.
All around, there's a balance between solidifying some concepts, vs continuing to innovate. Right now we're leaning a bit too hard toward chaos, and the industry would benefit a little from letting things mature.
I think a "best practice" should be a practice that is good to apply across a certain problem domain (regardless of where you work or what dev team you are part of).
And there are coding styles/guidelines which can apply only to a specific dev group or codebase. They can often be arbitrary, in the sense where it would be fine to do it in different ways, but one is chosen, for consistency (to promote maintainability/readability). They can be one way to achieve a best practice.
Day to day, it's probably fine to loosely call all these "best practices" since you apply them the same. But it is also sometimes useful to make the distinction, e..g, so you understand why a certain practice is being used.
The first example is a coding style, and a judgement call. The underlying "best practice" is to separate interface from implementation. There are various other ways to do that, of course, and need not be done like this. (Personally, I find this practice a little "enterprise-y", which I consider an insult.)
The example about version control also depends on the process and practice of the dev group.
Sadly, this approach seems to have been used in the interface software of my RAV4.
An actual best practice is based on objective criteria and experience, and can be shown to lead to better outcomes over the alternatives.
If that's not the case, then it is just a preference, indeed.
For instance, version control is a best practice. It objectively improves software development. So is unit testing, etc.
That friend simply didn't realize that "engineer" has different semantics with different historical evolution of word usage:
(1) "professional engineer" -- as in state license board and certification e.g. civil engineer
(2) "engineer" as a descriptive modifier -- e.g. "software engineer" and also some non-programming examples such as "audio engineer", "video engineer", "supply chain engineer": https://www.google.com/search?q=%22supply+chain+engineer%22
We could ask a similar question the friend asked: How can there be a "supply chain engineer" when there are no governing bodies for "supply chain certification" ?!?
It's because some people like to concatenate "engineer" at the end of a job role and others adopt the label and the usage gains wide currency. On the other hand, "dessert pastry engineer" hasn't really caught on so creating a fancier title doesn't always get accepted.
Back in the old days (1960s & 70s), the job titles of programmers on org charts -- especially at non-software companies like banks using COBOL, etc -- was "PROGRAMMER I", "PROGRAMMER II", etc. The "software engineer" seemed to be mostly popularized by software-focused companies like Microsoft, Silicon Valley. But now, even old companies like banks where coding is a cost-center instead of profit-center also have "engineer" in programming job titles.
So the world had no engineers before the creation of governing bodies? That doesn't sound right to me. Thus, I think this person's definition needs some tweaking.
Certainly those who did engineering-like work existed before governing bodies, you just never really knew whether they were any good, because there was no minimum set of competency defined.
Ironically, one might say this is what software development is like right now! It is both a blessing and a curse, the accessibility of modern software development is what makes it so great, pitfalls and all.
"Best Practices" means - given this problem set, these other engineers have tried a number of ideas and put together a framework, idea, code, whatever that represents a *good enough* solution.
There is no such thing as literal best, greatest, perfect. We're all just balancing tradeoffs in the "best" way we can.
For teams, consistency is more important than cleverness. If something needs to be "clever" then it is important enough to become consistently used because if the person who built the "clever" thing leaves, it becomes expensive to maintain it.
That's what "best practices" are, they are a consistent set methods that enough people have tried them that allows you to "stand on the shoulder of giants" and focus on more critical problems.
I've been working on something since approximately 2014 that I think finally has a reasonable chance of being correct (or at least useful ... for me). Now all I need to do is run a bunch of studies to see if this is actually a universal property or if it's just a bunch of bullshit that only makes sense to me.
But the point is that I don't want to use some weird self invented pseudo mathematical framework. I want there to be some obscure branch of mathematics that people already invented back in the 1800's that actually lets us define when some thing is complex and when it's simple. But as far as I can tell, it's just preference or poetics.
[
Okay, so there are a few things that sort of sound like they fit the bill, but when I looked into them I decided that they probably don't.
Cyclomatic complexity: This only works for if-statements (ie not for weird tangled OO object graphs or incomprehensible FP category theory operator soup) and some studies show that line count is a better indicator for defect rate.
Rich Hickey's Simple Made Easy talks are a gift to the software engineering community. But they're ultimately a poetic expression. You don't get to define one term and then pretend that you've solved how to write software. I view these talks as a very eloquent way of capturing the desire to create high quality craftsman like software. However, I don't believe that they're useful in a code review unless you need to appeal to pathos for some reason.
Kolmogorov complexity: This was really exciting to discover. However, I'm not really sure there's much here for programming. I guess you could use it to mathematically describe a boiler plate to apl spectrum. But I'm not sure you can use it to declare that any given point in the spectrum is better than any other point. Also, it doesn't really say anything about when mutable state is good or bad, etc. At best it's one metric out of many.
Information theory: Basically the same story with Kolmogorov complexity. You might be able to use this to decide that your variable naming is off, but there's so much more to good or bad software that this really can only be a single aspect at best.
]
The danger is that X keeps happening without the story of Y also being passed along; otherwise it turns into the Five Monkeys problem (https://intersol.ca/news/organizational-culture-and-the-5-mo...).
I'm not disagreeing with the author's friend's point. But at least if there's a story attached to the practice, then it's less of an appeal to authority and more of collective wisdom that can continue to evolve.
What may have been true 10 years ago may no longer be accurate or important but is still held up as a best practice today.
If allowed to evolve then we are all good but finding the correct speed of evolution (and helping everyone evolve at a similar speed) is harder than ideal. Flip-side of that is the organization or programmer that blindly chases the new.
Best practices are necessary. The value of "best practices" rests not on whether it is good. Its value is that there is an enforced standard across a business/organization. The existence of a standard (and recommended way) helps smooth out the execution/operation. In software engineering, that means easier refactoring, easier migration, easier tooling development, easier training, easier for people to move around within an organization instead of moving out...
I'd recommend any organization to find, install and periodically improve their "best practices". Just the virtue of their existence is a net positive to the business.
I always wondered the same thing, even now, az a so-called Lead Software Engineer. Frankly I call myself a programmer and that's it, maybe a "manager of sorts" now that I'm a "lead". I don't want to assume what others are doing, maybe engineering level work, but I'm rather an overpriced jack of all trades myself, who happened to have a nicely paying trade as a hobby, and an agreeable personality to sell it.
Architect is another glorified software position. Millenia of architects pushing the limits of human technology, often bearing huge responsibility for their plans, just so that later I can come in, advise my client to use the AWS vendor lock-in vehicle, and call myself an architect.
Words change over time and it's not like programmers AREN'T pushing the limits of human technology. What is much more advanced than your cellphone right now? Or the software that drives the Super Colliders? Or the software that runs an MRI?
I agree that our industry mis-appropriates the title "Engineer", but there is no reason to be so dismissive either.
I had something similar once I turned up all the logging on all the projects under my control. Suddenly 'there are tons of errors'. 'Yeah they were there the whole time because we ignored them'. Sort of like what happened with linux earlier this year. Turned up logging and suddenly everything is broken. It already is broken. You have just been ignoring it.
And if I can opine on your Spring Boot example, unit testing can sometimes be easier for mock purposes if you have a set of interfaces (vs concrete classes) to work with.
After reading about practices at JPL during the development of Curiosity, and the earlier work on Apollo (just two examples) I do think there is such a thing as an engineering practice of software development. I just don't think most of us are using it.
This is mentioned as bad thing, but having service interfaces really helped in a large Java project I worked, where we had to reimplement and extract some important code. Using the interface for the new code made it much simpler to use a radically different implementation, and also made devs think about what the real interface should be, vs just coupling to some implementation.
I think that's the author's original argument - not that interfaces are bad in of themselves, but that cargo culting is problematic.
Furthermore, starting with an interface oftentimes makes you create the wrong abstraction, however when you have a concrete implementation, in my experience extracting an interface becomes easier to do, though mostly thanks to excellent IDE tooling.
I have to fight the urge to ask for citations whenever I see someone pull out one of these chestnuts. Rather than be contentious, I just think about whether or not their argument needs the extra oomph of authority that they're trying to give it. My hope is that not rewarding disingenuity reduces its power.
We also use it to argue for opinion over empirical data points. E.g., tabs vs spaces. The “best practice” is some arbitrary number of spaces because “alignment”; this ignores entirely a substantial argument for tabs in the form of accessibility—you can make a tab whatever width you want, so if you’re visually impaired you don’t have to modify the code to read it and re-format it to the “best practice”. TLDR; tab indentation followed by space alignment would actually satisfy everyone’s needs, but it’s totally off the table because “best practice” is spaces.
Reason I avoid working in Java and especially the "senior java engineers".
> The logic from the senior engineer was that the interface represented the “contract” and the class the business logic.
This is basically religious dogma
However if instead you assume that "a class is just an implementation of an interface", then everything changes. Now the interfaces come first and classes are required to materialize them. In that paradigm objects only communicate with interfaces, never (or almost never) with other classes unless a specific implementation is required. Which is why an interface is always defined for a class even if there is no plan for other implementations of it.
Rather than a "contract", think of an interface as the description of a job. If you ever need to write a safety procedure, does it make more sense to write "In case of fire, call John; John happens to know how to extinguish a fire." or "In case of fire, call a fireman."? "Fireman" is an interface. "John" is a class implementing that job. It might be the only class in the codebase that implements it, but that is no concern of the caller. They just want that fire dealt with.
I would expect a software engineer to be working on safety-critical systems. Power grid control, military applications, etc. And I hope there's a massive amount more rigor applied to their work than there is to mine.
When it comes to code, I like to think best practices are those that make code easier to change and understand, without significantly compromising performance.
Developers who mainly target high performance with their code probably think my best practices suck, and so on.
At a practical level, what really matters is consensus within an organization. Organizations where people hold incompatible ideas of what good engineering is are basically doomed.
That said, it is ok to write down some preferences as a team/org standard that everyone can follow.
Just don't make the job a lawyers attempt at software engineering.
99.9% of the time they do, maybe you don't see them functionally and visually, but probably you aren't measuring security flaws, performance and specially ease of maintenance which goes unnoticed most of the time...
I do not want to live in a world where my code must conform to a Java Bean factory class. I align more with the skunkworks style of development.
I once work on contract on a project where everything was abstracted to hell and back. We spent 90% of our time trying to figure out where references pointed to in the code. Never again.
To discern the two is very easy. You write a piece of code. If someone else or even yourself can still understand it after a month, then you're practicing the "best practices".
Whereas, if you don't follow some "best practices" and they're still clear to others, they are just "developer preferences".
Best practices (generally opinions based on reasoning): language choice, KISS/DRY/YAGNI, linter rules, unit tests, static vs dynamic linking.
Standards (de-facto, at least): ISO, RFCs, PCI, and whatever is relevant for the industry the solution is for.
Not necessarily best. Best practices you get when you apply a darwinian approach in your org and try out several techniques before selecting the best. What is called best practices too often is a name for "we've done it this way since the beginning".
There sure is, that is what countries that have Professional Engineering titles have.
Some are, some aren't. Some are good practices but the state of the art evolves and better practices are uncovered.
And it's really had to tell the differences. it's a young field.
i think we probably need a more rigorous definition or else people will keep using "best practice" to justify what is actually a preference, and i think thats where conflicts start to happen within teams/orgs.
New batches of commonly accepted practices come into play with new technologies, though, and most of the "hot" technologies today are still so new that the "accepted practices" unique to them have still not settled down. So, yes, in that space, they change rapidly because they don't yet really exist.
Other than that I agree, most "best practices" are subjective and boil down to personal preference.
Depends on the language.
And sometimes you want to enforce a public contract of any implementation (current and future).
Personally for me, the biggest gain I see when writing against interfaces is that any class which expects a interface is already prepared for test-doubles, as opposed to classes written against concrete implementations which may even be initialised internally. Then just even starting to write a test becomes a so much bigger task.
Of course, everything with moderation, sometimes even moderation itself ;)
For example, you might want to pass around a class and only expose the getters and not the setters.
1. They are (usually) concise specification/contract for the implementation to follow, and for the client to use.
2. They permit substitution.
These are, from my experience, the principle and most useful reasons to make use of "redundant" interface definitions. What's worse is when people want alternative implementations but only have a concrete instance, they subclass it and break all kinds of contracts making their square peg fit a round hole.
This is less useful when you have ducktyping and consequently every lookalike is considered substitutable for each other.
Steve McConnell (Code Complete, Rapid Development, etc.)[0] used to be the Best Practices Editor for the IEEE.
It’s just as the author mentioned; no teeth. Companies are happy to pay for slapdash work (thus, undermining the drive to do good work), and employment tests often don’t really have much bearing on real-world engineering.
I’ve spent decades refining techniques and habits that I think work quite well. I occasionally write them down[1], which I find helpful in understanding them better.
The other one I’m not a fan is industry standard practice.
The catch? Knowing when it makes sense requires experience ;)
I currently work on a project that has about 1M SLoC in Java. Approximately 95% of the classes that have the @Service annotation are tightly coupled at the time of writing this. Yet, there are no issues with this approach.
Why? Because loose coupling is a nuisance if introduced at the expense of more code, which is how interfaces are currently done in Java, as opposed to them being implicit, based on implemented methods within a class, like Go does it.
In about 5% of the cases, we need more than one implementation and introduce an interface. In all the others, we don't. Now, what would happen if every single service would have an interface in front of it? The codebase would become far larger and it'd become more cumbersome to alter it.
Furthermore, IDE refactoring tools make it a non-issue - just choose which methods you want in your interface and create one, doing so at the point where you are clear about which methods are implementation specific and which aren't. Most smart tools will even offer you to replace your concrete classes with interfaces where possible.
A Practical Guide for Policy Analysis by Eugene Bardach. ( https://us.sagepub.com/en-us/nam/a-practical-guide-for-polic... ) and https://en.wikipedia.org/wiki/Eightfold_path_(policy_analysi...
Legal practices often follow from established best practices rather than the other way around.
There are many practices that solve a problem. Some of them have an intrinsic "better" to them. Of those, when trying to solve a problem you look at all of them. The one that fits your needs best is then the best practice.
> Don't be mislead by the word best in so-called best practices research. Rarely will you have any confidence that some helpful-looking practice is actually the best among all those that address the same problem or opportunity. The extensive and careful research needed to document a claim of best will almost never have been done. Usually, you will be looking for what, more modestly, might be called "good practices."
(as long as tabs stops/indent are 4)
I gave him the usual answer about how Software Engineers deal with low stakes and high iterability compared to Civil Engineers, but, honestly, he has a point."
I've argued for awhile now that Software Engineering with a big E should be licensed and regulated the same as any other Engineering discipline. Not all software is low stakes and fast changing. In fact I'd argue the most important software is never that. software for control systems, avionics, cars etc are very high stakes and have no reason to iterate beyond what is needed to interface with changing hardware. I think if software engineers had to be licensed to work on such things then those 737s wouldn't have fallen out of the sky and Tesla wouldn't be allowed to beta test self driving cars on public roads.
To those who ask what do you now call software engineers who don't work on those things, you are programmers. Or if you prefer a less formal term, coders. Engineer is a powerful word and I don't like how the we the IT industry have appropriated it for less critical tasks.
Firstly, most software is harmless. If it goes wrong people may be annoyed, but no one is harmed. But if I write software to control an aircraft, then it would have to abide by aviation standards. If I write financial software then I would have financial regulations to follow. Same for medical devices. So, there are standards for software but they are indirect and expressed in terms of the wider domain in which it runs.
> There are four types of critical systems: safety critical, mission critical, business critical and security critical.
Safety-critical systems > "Software engineering for safety-critical systems" https://en.wikipedia.org/wiki/Safety-critical_system#Softwar... :
> By setting a standard for which a system is required to be developed under, it forces the designers to stick to the requirements. The avionics industry has succeeded in producing standard methods for producing life-critical avionics software. Similar standards exist for industry, in general, (IEC 61508) and automotive (ISO 26262), medical (IEC 62304) and nuclear (IEC 61513) industries specifically. The standard approach is to carefully code, inspect, document, test, verify and analyze the system. Another approach is to certify a production system, a compiler, and then generate the system's code from specifications. Another approach uses formal methods to generate proofs that the code meets requirements.[11] All of these approaches improve the software quality in safety-critical systems by testing or eliminating manual steps in the development process, because people make mistakes, and these mistakes are the most common cause of potential life-threatening errors.
awesome-safety-critical lists very many resources for safety critical systems: https://awesome-safety-critical.readthedocs.io/en/latest/
There are many ['Engineering'] certification programs for software and other STEM fields. One test to qualify applicants does not qualify as a sufficient set of controls for safety critical systems that must be resilient, fault-tolerant, and redundant.
A real Engineer knows that there are insufficient process controls from review of very little documentation; it's just process wisdom from experience. An engineer starts with this premise: "There are insufficient controls to do this safely" because [test scenario parameter set n] would result in the system state - the output of probably actually a complex nonlinear dynamic system - being unacceptable: outside of acceptable parameters for safe operation.
Are there [formal] Engineering methods that should be requisite to "Computer Science" degrees? What about "Applied Secure Coding Practices in [Language]"? Is that sufficient to teach theory and formal methods?
From "How We Proved the Eth2 Deposit Contract Is Free of Runtime Errors" https://news.ycombinator.com/item?id=28513922 :
>> From "Discover and Prevent Linux Kernel Zero-Day Exploit Using Formal Verification" https://news.ycombinator.com/item?id=27442273 :
>> [Coq, VST, CompCert]
>> Formal methods: https://en.wikipedia.org/wiki/Formal_methods
>> Formal specification: https://en.wikipedia.org/wiki/Formal_specification
>> Implementation of formal specification: https://en.wikipedia.org/wiki/Anti-pattern#Software_engineer...
>> Formal verification: https://en.wikipedia.org/wiki/Formal_verification
>> From "Why Don't People Use Formal Methods?" https://news.ycombinator.com/item?id=18965964 :
>>> Which universities teach formal methods?
>>> - q=formal+verification https://www.class-central.com/search?q=formal+verification
>>> - q=formal+methods https://www.class-central.com/search?q=formal+methods
>>> Is formal verification a required course or curriculum competency for any Computer Science or Software Engineering / Computer Engineering degree programs? https://news.ycombinator.com/item?id=28513922
From "Ask HN: Is it worth it to learn C in 2020?" https://news.ycombinator.com/item?id=21878372 :
> There are a number of coding guidelines e.g. for safety-critical systems where bounded running time and resource consumption are essential. These coding guidelines and standards are basically only available for C, C++, and Ada.
awesome-safety-critical > Software safety standards: https://awesome-safety-critical.readthedocs.io/en/latest/#so...
awesome-safety-critical > Coding Guidelines: https://awesome-safety-critical.readthedocs.io/en/latest/#co...