370 comments

[ 3.5 ms ] story [ 355 ms ] thread
I get your friend, and there's another point he can make: Imagine a world with self taught Civil Engineers.
Oh yeah the last bridge collapsed, but that is a known issue. It is fixed in this bridge, trust me.
Blame the contractor is what you normally do in this case :-)

I once built a system reverse engineering a program used for soil analysis to see why one of our bridges fell off its suports.

Can you tell us more? This sounds oddly fascinating.
That’s sort of the Tacoma Narrows Bridge story.
To make the comparison fair, in that world civil engineers would also have the ability to change the laws of physics.
And the bridge collapsing would usually not kill people but strip all their clothes.

Also you can start a bridge in your garage.

The clients also usually don't want to pay for a stable safe bridge because the collapsing one is good enough.
If only building a bridge in your garage could make you a billionaire. People would build bridges like crazy.
Or you can just compare them to software engineers that work on critical software like launch systems and nuclear reactors.

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.

Yeah, that’s a very good point! I imagine if civil engineers could change physics, they’d lockdown what you’re allowed to change for critical systems. And like you said, systems that don’t need the 9s can experiment and learn.
Pretty much. IT as a field is a toddler. But it makes so many people happy we don't care it's still at the anal stage.

Maybe in a century techs and standards will stabilize.

>Pretty much. IT as a field is a toddler.

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.

It’s almost like we have different standards for different types of engineering.

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.

Which was left in the hands of a small elite from the beginning. I don't think reddit could have been born that way :)
Pretty sure this is because most of our public investing goes towards spying programs instead of more funding for places like NIST.

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.

nuclear engineering is a direct combination of applied physics, civil engineering and mechanical engineering, all having a long history.

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.

Steven Sinofsky gave a talk and said something to the effect of, we've been building roads, bridges and edifices for thousands of years. So, best practices and solved problems abound---and even then we still get it wrong sometimes. Whereas, software engineering is maybe 70 years old (generously)? So, there is much to learn and a lot of "baseline" knowledge that has yet to be established. I think it's a good way to think about things.
Undergrad CS profs are teaching everyone that theres "Nothing new under the sun."
Eh, I mean we've been building computer chips for approximately the same amount of time as computer software, and it's pretty clear chip engineering is more like civil engineering than software engineering. I would guess many of the best practices in bridge building in the modern day were developed in the last 70 years.

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.

> Eh, I mean we've been building computer chips for approximately the same amount of time as computer software, and it's pretty clear chip engineering is more like civil engineering than software engineering.

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.

Sure, and civil engineering is really different from chemical engineering. But those are minor compared with the differences between physical engineering disciplines and software engineering.

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)

Well I think this is just a case of easy Software Engineering vs hard Software Engineering where the requirements are hard to satisfy.

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.

Buildings are constructed correctly closer to 10% of the time, I assume. The ones built incorrectly still get used, just with lower lifespans and are more likely to run into issues.
Civil (and other engineering) got better because there was motivation to improve that came from multiple directions: literal lives at stake, the pride of good craftsmanship, iterative or even grand steps forward in knowledge, etc.

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 feel like I already spend 90% of my day gluing together various disparate APIs. Is this the logical conclusion to software development?

I adore the craft-like parts of software dev, wouldn't trade it for anything.

What about we apply this to software engineering?

> 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

Define "specifications" and "conform" in terms that I might hear from a non technical client.
The engineer is responsible for taking non-technical language from the client and turning it into technical engineering specifications. Why does this fall to the client in software?
That is what contracts are for.
The software is as sturdy as the day it was written, there has been no deterioration - if your copy has become broken, the builder can easily supply another copy using his own silver.

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.

Unfortunately only consulting and high integrity computing are the main areas where software companies get liability for delivering faulty products.

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.

This is a symptom of the lack of knowledge not a cause. Imagine you want to built a building but no one really knows how, then copying successfully completed buildings, and established construction engineers and companies is a pretty good idea. That's what's going on in SE.
The difference is the feedback is pretty incontrovertible if you build a building and it falls down. If you use composition instead of inheritance, the evidence of whether you're right or wrong comes in the form of ... slightly faster refactoring two years later? Maybe?

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.

It's both, as it's a feedback cycle. This industry, like many others, rewards narcissism and loudmouths above all else. It does so in the large (e.g. Fowler or Uncle Bob worship; "ex-FAANG" cache) and in the small (the self-promoting engineer who touts his work even if it's not all that great gets promoted over the "soft-power" engineer managing tough projects lowkey). In this environment the symptom feeds the cause, because nobody stops to question whether the symptom is even a symptom. The root cause, ignorance, is entrenched and made deeper, which feeds the symptom. And so on.
I just want the fuck out, there no realistic alternative.
Furthermore, there are far fewer physical constraints in software, so the range of possible designs is dramatically wider.

(Actually I dare say that sotware itself has no physical constraints at all: software artifacts and software executions do.)

Which is why I don't buy the "software has only been around for 70 years so give it time" argument. Software has nothing to be grounded in like other engineers do with physics. It's most likely always going to be endless cargo culting.
That's simply not true. Software is grounded in mathematics. Most people just try to ignore that fact for convenience.

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.

As an oficially qualified computer scientist, I can say that software is grounded in mathematics, but this does not imply what you're thinking. *All* formalisms, including mathematics, are in the end nothing but an incredibly precise language to talk about ideas in your head. Programming languages are created for communication, so this is specially true for them.

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.

> 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 hat 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.

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.

Great example!

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?

Many times there are authorities that have formalized protocols for systems involving people. For example, the FAA has prescribed thresholds where pilots should be alerted of possible failures when navigation system measurements have exceeded those thresholds. Other times thresholds like those can be found just through user testing and feedback. The goal there is to ensure safety without losing the confidence of the user or overwhelming them with information.

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.

It's more like mathematics. While it's true that everyone can invent their own maths, this is only really done in advanced academia for research. Almost everything in practical use is standarized. No-one is arguing about whether you need integration or what the right notation for differential equations is.

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.

Also, there isn't that much in the way of scientific grounding.

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.

Math. Which seems that many practitioners are proud of not knowing
Logic maybe but a very large amount of software written does not use much if any math beyond the very basics.
Lots of people in other engineering disciplines don't use math beyond the very basics either. A large amount of parts are designed in CAE software which handles most/all of the mathematics. And in some larger companies, the person designing the part and the person testing the part are on different teams.
Math provides no answer for a lot of the problems one encounter in day to day software development. It does not help you decide how much test coverage you need,it does not help you decide how to review, it does not help you figure out what features are desired, it does not help you collaborate with the juniors etc etc.

I agree that math describes limitation to computer science and formalisation. But software engineering is more than computation.

How about math? Complexity theory, all kinds of logic, computational theory, category theory?
Honest question. How does that help?

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?).

Computer Science?

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.

Well, if you make broad generalizations like that, then software engineering has mathematics as a foundation.

Perhaps you don't want to make broad generalizations?

> I suspect it is a mix of cognitive science, linguistics, and anthropology.

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.

I'm a computer science and computer engineering major, and I've never once heard the term "computing science". Is there a context in which this term is regularly used?
> cognitive science, linguistics, and anthropology.

Would love to hear your thoughts on this, esp. the linguistics and anthropology piece.

> I suspect it is a mix of cognitive science, linguistics, and anthropology.

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.)

Programming changes practice quickly and often because it's cheap to do so compared to physical engineering which is slowed down by execution time, high materials cost, and sunk costs.

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?

Having an interface for a single implementation is just redundant. A class already has an interface - it's public API.

Other than that I agree, most "best practices" are subjective and boil down to personal preference.

> Having an interface for a single implementation is just redundant. A class already has an interface - it's public API.

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 ;)

I usually agree but sometimes you want to reduce the exposure of the public methods of the concrete class even if there's only one concrete implementer.

For example, you might want to pass around a class and only expose the getters and not the setters.

Having an interface let's you introduce versions or alternative implementations easily, this is important in a long run. It's much easier to handle the transitions, because you can have both versions in your code base and you can easily switch back to the old one if necessary. When you start with a class and you want to do similar thing, you either YOLO it and change everything at once, or you need to introduce an interface and replace every usage to use the interface to achieve a safer transition and you are back at the interface-class implementation with an extra pain.
Interfaces serve two roles:

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.

I feel like the responses to this comment are somewhat proving the point around most things being preference. ;)
I am all against standards and engineering boards defining what is right and what is wrong, but at the same time I also favor software developers being held civil and criminal responsibilities for the outcome of their work. It is pretty hard to have the second without the first, so here I am at a crossroads.
> Are Software Engineering “best practices” just developer preferences?

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.

(comment deleted)
It’s best practice to apply best practices when it makes sense.

The catch? Knowing when it makes sense requires experience ;)

To some extend best practices are just developer preferences, but some best practices are also due to experience which has shown alternatives to attract problems down the lane.

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.

Are civil engineering "best practices" just legal preferences?
One of the books I picked up to settle an argument about best practices once...

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."

A LOT of coding style, abstraction style, function vs inline is just preferences. This is what makes code reviews hard. Both the author and reviewer can easily fall into the trap of trying to "correct" the other person - without realizing that they are merely forcing preferences on the other.

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.

I hope at least that we're in a phase of the profession where we're "discovering" the actual best practices.

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.

We're definitely still figuring out what the best practices are. In my relatively short career as a software developer, we've already flipped back and forth between separation of concerns is important when it comes to views, styling, and logic. (Frontend dev)

Gone are the days when we threw together a php, html, and JavaScript in one file... wait, or is it?

Give it a couple years, it'll come back around!
The issue here is that people abuse the term and call many things and anything a "best practice".

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.

Software engineering seems partially creative partially technical - so on the creative parts, yes absolutely teams should self define their preferences. Scrum vs agile vs whatever else IMO should be a team/org preference. However like someone else said some engineering has to be liable for criminal prosecution in some cases. So you need some practices to be enforced.
Sure, so who defines which parts are highly technical? We can all be in agreement that things like cryptography should use well known and vetted libraries, whereas something like a REST API interface can be a little more relaxed with adherence to a standard, but where do we draw the line?

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.

It’s a difficult question and I’m not qualified to answer it as an amateur tbh.
Best practices create a shared experience that can help get you out of trouble when that practice was a bad decision.
> How can Software Engineers call themselves engineers when there’s no rules, governing bodies, or anything to stipulate what true Software Engineering is?

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.

Not quite, a governing body is what stipulates who can be called an engineer and who cannot (at least this is the case in Canada.)

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.

The two aren't mutually excusive. What I mean is, you can develop a preference for doing a software engineering task according to a best practice. Getting into the habit of using one or more time-tested practice(s) will only benefit you over time.

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...

I did say that to be fair, I just omitted it from the post.

The question was more of a jumping off point for my thoughts on the practices vs. preferences question.

Fair enough! Thank you for posting the article and getting this discussion going, by the way.
I'd say that a lot of devs do have a hard time distinguishing "best practices" vs "the way I like to code". It's also tough because many of the motivated devs who can push these initiatives through need help with the sometimes subtle difference.
There is value in predictability, even if it stems from someone else's preferences.

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.

100% that's true! I'm not saying developers having preferences and everybody abiding by them is a bad thing, more just that a lot of what constitutes "best practices" are often preferences and we should call them that.
Doesn't that kind of imply that everyone's opinions are equally valid? If 95% of your profession is on the same page with a certain practice then I'd argue it's really not reasonable to go against the grain without a very good reason.

I think "best practices" strikes a good balance between things that are personal preferences and things that are laws.

I'm not sure if there's anything 95% of developers are on the same page about.

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.

From what I've seen, every company has a different idea of what _best practices_ are.

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.

Yeah it does. Software is basically a mental model and different people have different mental models of the world so we make up languages/practices/etc. that fit those models.

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.

Maybe we just disagree about what constitutes best practices. I can't speak much about Java land, but I wouldn't describe rebasing in general as a best practice without further context. If you're working on a team that always rebases feature branches then your preference for not rebasing doesn't seem valid to me.
I agree, at least in my experience of android development, "Best Practice" often means: what I read on Medium, or what Google said.

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

1950's onwards they used ribbon cables close to surfaces for household wiring. It was best practice, just not today's.

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.

In many countries this is coded (mandated by standards), it is not a best practice.
Yes and no.

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.

The only objective thing for best practice is simplification. Problem with loose coupling, OOP etc... is that a lot of it sounds like "done" right but becomes complicated over time - even though it might be a good idea. So only "KPI" for best practice should be simplicity over time.
Serious question. Can humanity define what it means for something to be simple or complex? It seems like we all have an intuition that such a thing should exist. However, most times when I talk to people about it, the conclusion I reach is that they're talking about what is familiar or unfamiliar.

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.

]

In contradiction with the first paragraph, there are definitely fields of software engineering with external regulation, auditors, etc. I'm thinking of the banking sector and realtime critical software, like in avionics and such.
Yeah, I told him that, but by and large most developers don't work on those problems.
Right now I am working on converting a front end application written in angualar/typescript using a monorepo technology called nx.dev into a micro-frontend architecture. All the teams that have been contributing code to the project never bothered to use nx in the way that it was intended and disabled linting for the entire project. The thing is if people had followed the linting rules it would have made my life 1000x times easier because now I have to take a scalpel to the monolith they've made and break it down into smaller parts. Linting rules would have told them to respect module boundaries and warned about circular dependencies. Now I have to clean up the mess.
That falls clearly into one of my best practices 'look at the logs they are trying to tell you something'. But like all 'best practices' it can be take too far. So now you have tons of logging but can not actually tell what is going on because there is too much noise.

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.

> the senior engineer had defined every single service class as an interface and then implemented that interface in an actual @Service. The logic from the senior engineer was that the interface represented the “contract” and the class the business logic.

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.

There is a large difference between dogmatically declaring that every single service needs an interface, versus just introducing them at the point where you actually need more than one 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.

Exactly, it would've made total sense to pull it out into an interface in other situations, but simply felt like a preference here.
Right, but have you ever worked in a place where no practices at all are being followed? Where there are hacks after hacks, giant classes with giant methods, no interfaces, static methods, bad names everywhere, you need to find a bug? good look, you want to write a test to avoid regression? Ok that would take you 5 times more time.

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 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.

Yup, I 100% agree. The point of the post wasn't to bemoan practices, more just that it's frustrating to be told repeatedly that a certain thing is a "best practice" when really it's just what the developer who wrote it preferred.

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.

> But just discarding best practices because no one understands the reasons behind is also silly.

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.)

Most places I have worked had zero agreed standards. It wasn’t a problem at all. And people didn’t waste their time getting into fights about how to interpret the “agreed standards” or policing it. Great!
I can't imagine someone arguing that avoiding tight coupling is a personal preference.
I can.

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.