We have found that by changing our software/system architecture we have also inadvertently changed our organisation structure.
- Inverse Conway Law or just Roy's Law ;-)
Before we had four cross functional teams, working on a single application, everyone felt responsible for it, worked overtime to fix bugs etc, we had good communication between the teams.
But after we switched to microservices the teams became responsible for just a part of the system, their microservice(s). Whenever we had an outage, one team was left to fix it, the others just went home. They stopped talking to each other because they didn't share any code, no issues... they stopped having lunch together, some things got way worse in the organisation, all sparked by a 'simple' architectural change, moving to microservices.
That reminds me of a place I used to work at, where initially we had DBAs embedded in the teams. They switched that and the DBAs were all grouped together and all hell broke loose. They were always have meetings, throwing out emails about they were dictating this and that, and had very little direct communications with the teams they were supposed to be supporting.
I ended up leaving during the peak of all of this, but in an exit-interview, a director asked me about the problems this was causing.
> They stopped talking to each other because they didn't share any code, no issues... they stopped having lunch together
Was that accompanied by any growth in company size? I've found that this happens when a group grows past about 15 people even if the structure doesn't change.
This outcome could be considered a feature of microservices: by abstracting the functionality into more tightly-contained units, failures are more isolated.
Sounds like the organization needs to do other things to keep people from getting siloed, though that gets increasingly difficult at scale. Well-defined SLAs (along with monitoring and reporting of those SLAs) are also necessary so that microservice failures can be understood in the right context.
I have seen new systems/software implemented just to isolate/remove parts of an organization. Worse I have seen it done when the existing system/software was just fine.
> They stopped talking to each other because they didn't share any code, no issues... they stopped having lunch together, some things got way worse in the organisation, all sparked by a 'simple' architectural change, moving to microservices.
Oh, it is definitely a problem from a social/cultural standpoint. But from the point of software architecture (and, therefore, development organisation), too much (or even any) communication between teams working on discreet, separate units can become detrimental.
It is perfectly fine that the people communicate, and even helping each other to improve tech skill should be encouraged; however, decisions about their respective products should be contained within each team, with clearly defined interfaces and usage documentation.
> decisions about their respective products should be contained within each team, with clearly defined interfaces and usage documentation.
In order to make those decisions and define the interfaces, you need to know a lot about how your software is going to be used. That will be much easier if you have good communication with the other teams and understand their goals and motivations.
I disagree. In my experience, direct coordination on interfaces tends to create unnecessary special cases (hey, can you add this field to your API, just for us?) which add complexity and make maintenance more difficult down the line.
The main advantage of distributed system, and particularly microservices, is the ability to have each system completely independent: individual components can be written in different languages, running on different platforms and use completely independent internal components. Basically, it is just like using an external library, component or service: the authors provide documentation and interfaces, and you should be able to expect it to behave as advertised.
> In my experience, direct coordination on interfaces tends to create unnecessary special cases (hey, can you add this field to your API, just for us?) which add complexity and make maintenance more difficult down the line.
If you just implement all requests directly, you're for sure going to end up with a horrible interface. You should approach API design the same way that UX/PM approaches UI and feature design: take the time to understand _why_ your partner teams/engineers are requesting certain changes and figure out the right interface to address their problems.
Oh absolutely, but direct communication between teams is not the right method for that. Which is why every product, no matter how "micro" a service, needs to have a dedicated product owner/manager who is responsible for defining functional requirements.
Edit: I just noticed that "PM" in parent comment. Basically, product managers are not just for UI and customer-facing products.
The idea that "functional requirements" can be decided independently from "technical architecture", as opposed to in interplay with each other, is exactly the opposite of what I've learned from good experiences with "agility", although some people seem to somehow take it that the opposite.
But yes, you can never just do what "the users" ask for. The best way to understand what they need is to be in conversation with them. Silo'ing everyone up isn't going to make the overall product -- which has to be composed of all these sub-components working well with each other -- any better.
> The idea that "functional requirements" can be decided independently from "technical architecture"
Oh it absolutely can; it's just that it usually is not a good idea. But I'm not talking about the process of reaching that decision, I'm talking about the responsibility to reach them. Functional and technical decisions are separate, but in most cases should be defined in conjunction.
> Silo'ing everyone up isn't going to make the overall product
This is true for certain types of product, and less so for others; you need to clearly understand what type of product you're building, and be ready to adapt as it changes (or you have a better understanding of it). In a nutshell, the more compartmentalised a product is, the isolation between the teams becomes more beneficial. Which brings us full circle back to Conway's Law.
> But I'm not talking about the process of reaching that decision, I'm talking about the responsibility to reach them
Of course you're talking about the process. Your claims that "direct communication between teams is not the right method for that," and "communication between teams working on discreet, separate units can become detrimental," for instance, are about process.
I don't think this conversation is going anywhere, but from my experience, lack of communication between teams working on discrete, separate units (that are expected to be composed to provide business value), can become detrimental. And that's about process.
Well, from a systems standpoint, it means a given "problem" is isolated to a single service, and is therefore not impacting the other services or interrupting the work of the other teams.
But culturally, it would be nice if people helped each other out from time to time...
That's only true if any given problem is isolated on a single service, because while you are making intra-service problems much cheaper and faster to fix, you are also making inter-service problems almost impossible to fix.
Um, no. The real world is not that simple. It would be nice if it were.
Or perhaps your statement is correct, but in the real world components are never sufficiently separate. So, while your statement may be correct by definition, it is not useful.
I can imagine there being a normal distribution of 'separateness' of software and the rare top tail-end of the distribution gets it perfectly right, most are in the middle somewhere between 'service oriented architecture' and 'ball of mud' and some are just at plain ball of mud.
Well I meant it quite literally: if it is not clear which component has the bug, the components are not separate enough. You also say:
> in the real world components are never sufficiently separate
But the separation of components is not an issue of "real world", it is a function of design and implementation. It is absolutely to the developers how independently the components will be implemented; if there is no way to test them in isolation, then they are not really separate components.
Take this website, and your browser, as an example. They are obviously connected, as you're using the latter to access the former, but they are completely independent: you can access other pages with the browser, and you can use other methods (other browsers, or curl, or Postman etc) to access this page. Each can be tested separately, and even when they are used in conjunction they don't directly depend on each other, but rather on a set of standards (HTTP, HTML, CSS etc) understood by both.
Yes, but then you find web pages that attempt to determine which kind of browser requested the page, and changes what is sent back in order to work around the broken-ness of specific browsers. Yes, it's supposed to be a nice clean interface specified by standards. But in the real world, as they say, all abstractions leak. "All" may be an overstatement, but the problem is real. We never separate things cleanly enough.
Sure. Look, despite the impression I may have given, I'm not arguing for separating things badly. The cleaner the separation, the better. It really makes a difference.
Probably we can agree that a company will be more productive if the engineers are learning from each other and generating ideas together? So if you've got a team of engineers who don't like working with people, it's probably in the company's best interest to set up a structure that explicitly encourages more communication.
This depends very much on the team size. Having a team of 20 people communicate in the way you describe below is insane overkill. Having a team of 100 do so may save everyones' sanity.
Moving to microservices is anything but a simple change. Your experience is one example of why microservices are not automatically a good idea. Normally, the advice is that they might be a good fit if you have isolated teams to begin with, and for different reasons.
> “Before we had four cross functional teams, working on a single application, everyone felt responsible for it, worked overtime to fix bugs etc, we had good communication between the teams.”
This actually sounds very dysfunctional, but with the type of positive PR spin that product / executive management wants, basically anyone who believes “cross-functional” is anything more than a buzzword.
Would love to know what the engineers thought about working in that environment (which sounds like a monolithic, too-many-cooks, zero specialization situation likely negatively affecting career growth & routine skill building).
Types of bugs or failures are not separated into specialized areas, rather it’s one “cross-functional” unit. It’s like building a monolith class in software instead of following basic principles like Single Responsibility Principle and organizing workflows according to independent specializations.
This part is often much worse than the overtime part, because it means you’re expected to sublimate your personal career goals in favor of whatever arbitrary thing needs done for the sake of the cross-functional unit.
When I hear someone describe communication between cross-functional team members as “good” or “effective,” then I know it’s a big lie, and most probably it’s a disaster of overcommunication where product managers or non-tech leadership have a stranglehold on decision making when really engineering should be autonomous in these cases exactly according to independent specialization.
Hyrum's law is highly relevant to anyone who makes software libraries.
"With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody."
I.e. any internal implementation details that leak as behavior of the API become part of the API. Cf. Microsoft's famous "bug for bug" API compatibility through versions of Windows.
They might become part of the API in a superficial sense, but if you broadcast clearly that undocumented behaviors are subject to change, then users can decide if they want to accept that risk and won’t have a valid complaint if they want the not-covered-by-the-contractual-API preserved or become surprised by a change.
> if you broadcast clearly that undocumented behaviors are subject to change, then users can decide if they want to accept that risk
That sounds nice in theory, but doesn't really work in practice. If you're building infra and a core piece of your company's product relies on these undocumented behaviors, you can't just change the behavior and shrug your shoulders when the whole product breaks. Similar if you're providing an external API to users/customers, you can't just break their stuff without worrying about it.
I'd add, if the API is meant to implement a protocol but doesn't implement it quite correctly, you may object to the misimplementation, but if your code has to work with the implementation, you have to adapt to their bug. It's not even a matter of undocumented behavior.
Experienced recently as a consumer of an API when letsencrypt made a breaking change to implement the protocol correctly. Broke my code which relied on their original incorrect implementation.
While you might not view their complaint as valid, what if the change you made cuts off service to the customer? And what if the service you provide is in the critical path for the customer, such as hosting, payments, or even power?
I can testify to this personally, having worked at a payments processor and accidentally broken integrations. The business, as it should have, had little tolerance for me changing a depended upon API, even though it was not documented
The struggle here is that it's not always clear what behavior, buggy or not, is intended behavior. Especially as the complexity of an API endpoint or method increases, for example with large input models or mutable system state at the time of request.
It's very common for Conway's law to be regarded as some kind of warning, as if it's something to be "defended" against. It's not. Conway's law is the most basic and important principle to creating software at scale. A better way of stating Conway's law is that if you want to design a large, sophisticated system, the first step is to design the organization that will implement the system.
Organizations that are too isolated will tend to create monoliths.
Organizations that are too connected and too flat will tend to create sprawling spaghetti systems. These two cases are not mutually exclusive. You can have sprawling spaghetti monoliths. This is also one of the dangers to having one team work on several microservices; those microservices will tend to intermingle in inappropriately complex ways. Boundaries are critical to system health, and boundaries can be tuned by organizing people. Don't worry about Conway's law, leverage it.
A personal rule of thumb I derived from the ninety-ninety rule is this: "Before starting a project, ask yourself if you would still do it if you knew it would cost twice as much and take twice as long as you expect. Because it probably will."
I totally agree. I tend to phrase it a bit differently: "If you need to know how long it will take before deciding if it is important enough, then it is likely not important enough."
Another kind of corollary: "If the business will go under if we don't get this done by X, then we probably need a new business plan, not faster development".
These are rules of thumb and there are definite places where they don't hold, but I've found it genuinely useful to consider when the inevitable tough questions start to get asked.
I see the 90% rule as a recursive function: First we get 90% of the whole work in the first iteration, then 90% of the remaining code (now we are 99% complete), then 99.9% and so on.
The iteration is stopped when the software has enough features and an acceptable level of bugs to be considered complete.
What complete is depends entirely on the field of the software.
For a proof of concept software we can stop after the first iteration, but for a safety critical software we might need 3, 4, or even more itarions.
I've found that under-promising and over-delivering requires me to quadruple my best estimate.
Unfortunately, lots of us bid against people who over-promise. By the time the project is obviously behind schedule, it's too late, and the client can't switch to someone else.
Murphy's Law has electrical engineering roots. I have a fun anecdote.[0] My wife is electromechanical and I'm computer science so we would work on projects together since we make a good team. I remember in college I was working with my wife on one of her projects and we were using force transducers. The damn things kept breaking at the worst times so we kept calling it Murphy's Law. After a while we looked it up. Turns out Murphy was working with transducers when he coined the phrase [1]. So I have this little back pocket anecdote about the time I got to use Murphy's Law in the original context. Which I can bring out in times just like this.
Everyone always conveniently forgets Price's Law (derived from Lotka's Law) It states that 50% of work is done by the square root of the number of employees.
Interestingly, Price's law seems to indicate 10x developers exist because if you have 100 employees, then 10 of them do half of all the work.
This idea is particularly critical when it comes to things like layoffs. If they get scared and leave or they are let go for whatever reason, the business disproportionately suffers. Some economists believe that this brain drain has been a primary cause in the death spiral of some large companies.
You have to completely abandon reality to get rid of the idea. If 60 of the remaining 90 devs did NOTHING, those 10 devs would still be 2.5x better than the rest.
To take things further, make a bell curve chart. Put 50% of the area under the top 10%. Now, divide up the rest however you'd like. The only way to make this happen is for a huge percent to not only contribute zero, but to be actively hurting development to an extreme degree.
I have never found a 100 person company where 60% or more of the company was contributing absolutely nothing. I have never seen a company where a large number of people were actively harming the company and the company survived.
It's extraordinarily difficult to quantify this. Anecdotally i believe I've worked with people who were net losses for the company, devs whose contributions would be better if they did nothing. And yet those same people often shine in specific areas, like "angular knowledge" or something like that.
> I have never seen a company where a large number of people were actively harming the company and the company survived.
"To survive" is a temporal measure.
It's pretty common for companies to survive on a successful product (or group of products). The rest of the company was a shell and revenue sink for that line.
My understanding of your model must be inaccurate somehow. Here's what I think I'm hearing:
- the distribution of productivity of devs in an organization of N * N devs can be approximated as: N devs who are "Nx", and the rest of the devs are "1x" (Price's Law, assuming a binary distribution for simplicity)
- the value of "x" is constant for all sizes of organization (if it were relative "some are 0.1x" would be a change of units, not an abandonment of reality)
This would yield the extremely surprising result that the total dev production of an organization scales quadratically with the number of devs, so what am I misunderstanding?
It actually looks more like an exponential curve with 50% of the area under the curve fitting in the last few devs. If we normalized the "flat" side of the curve to be a 1x dev, the we probably have 80 1x devs, 5 2-3x devs, 5 4-6x devs and 10 8-9x devs.
Rather than quadratic scaling, we're dealing with scaling by root. This actually meshes very well with the "mythical man month"
If we almost double from 100 devs to 196 devs, we only go from 10 to 14 devs doing half the work.
We've already accepted that 10 devs were doing half the work of 100 devs. We've also accepted that those devs must be giving it their all. So, doubling the devs, but only getting 4 new people to fill the doubled top 50%. Either we have some new 20x devs or the actual amount of work hasn't increased at the same rate.
I would still say that is probably incorrect though. The "mythic man month" doesn't apply to total work done -- only to total useful work done. As the social complexities increase, the ratio of other work decreases, but the those top developers will still have to carry both increases (to at least some degree) in order to still be doing half the work.
I suspect that as the social overhead increases, you should see three interesting cases. Those who can deal with the social overhead more quickly, so they have more real work time to compensate for being slower at it (potentially bumping a 5x dev with better social strategies higher). You could see the opposite where a 10x dev simply loses all their time in meetings. You could also see where a 1x dev with better social strategies handles most of a 10x devs social workload so that dev can instead focus on coding (it's rare, but I've worked on teams with 1-2 devs who did little except keep the team productive by fending off the bureaucracy).
My first real job was as a contractor working with middle management at Bristol-Myers-Squibb. What I saw there was easily that absurd, and that company still exists.
I have always liked Postel's law (and Jon -- what a great human being he was) but I no longer like it as I used to.
The reason it's a really great idea is that it says you should engineer in favor of resilience, which is an important form of robustness. And at the same time, "strict in what you send" means "don't cause trouble for others.
However there are cases where "fail early" is more likely to be the right thing. Here are a few:
1 - Backward compatibility can bite you in the leg. For example, USB Type C (which I love!) can support very high transfer rates but when it can't it will silently fall back. So you could have a 40 Gbps drive connected to a 40 Gbps port on a computer via a cable that only supports USB 2 speeds. It will "work" but maybe not as intended. Is this good, or should it have failed to work (or alerted the user to make a choice) so that the user can go find a better cable?
2 - DWIM is inherently unstable. For users that might not be bad (they can see the result and retry) or terrible ("crap, I didn't mean to destroy the whole filesystem").
I see these problems all the time in our own code base where someone generates some invalidly-formatted traffic which is interpreted one way by their code and a different way by someone else's. Our system is written in at least four languages. We'd be better off being more strict, but some of the languages (Python, Javascript) are liberal in both what they accept and generate.
This aphorism/law was written for the network back when we wrote all the protocol handlers by hand. Now we have so many structured tools and layered protocols this is much less necessary.
Being liberal in what you accept has turned out to be a security problem. This is especially so when this maxim is observed in a widely-deployed piece of software, as its permissiveness tends to become the de-facto standard.
I feel like Fonzie's Law would be a worthwhile inclusion: "The best way to get the right answer on the internet is not to ask a question; it's to post the wrong answer."
Remember that all is opinion. For what was said by the Cynic Monimus is manifest: and manifest too is the use of what was said, if a man receives what may be got out of it as far as it is true.
I encountered a literal version of this the other day.
I’ve been looking at some disused AI systems, which were all written in Lisp back in the day.
In an attempt to remain relevant, at one point in the early 2000s someone tried porting one of them to Java. By first writing a Lisp interpreter in early 2000s Java. So the system had all the old dynamic Lisp programs as giant strings, embedded in a fugly static class hierarchy.
A mutant variation of this: Greencodd's Rule: "Every sufficiently complex application/language/tool will either have to use a database or reinvent one the hard way." (from c2.com)
And then there is Virding's First Rule of Programming:
Any sufficiently complicated concurrent program in another language contains an ad hoc informally-specified bug-ridden slow implementation of half of Erlang.
Variation 2: If you factor duplication heavily and go ultra-meta, you'll end up with Lisp or a clone of Lisp. However, only Lisps fans will be able to understand the code.
Yes, this doesn't strike me as good quality content at all. But it's a large list which lets everyone pick something and chip in which drives engagement.
If this sort of content is the sort that this community increasingly selects for then it is perhaps time to look for fresh pastures. ( I don't however know if this indicative of HN's current community or just an 'accident' - I'm sure there have always been examples of poor quality near the top at times).
I think not just this one, a few of the top ones are of similar vein at the moment. Seems a bit off-colour, as usually the quality of content was rather consistent.
There is an entire poster of funny 'laws of computing' that was created in 1980 by Kenneth Grooms. It's pretty amazing how many of these are completely relevant 40 years later...
It's hard to find the original piece of art, but my uncle had this hanging in his office for a long time, and now it's hanging in mine.
I transcribed it in a gist so I had access to them for copy/paste.
You can have quick-and-dirty for initial release, but it's rarely practical from a maintenance perspective.
A related rule: Design software for maintenance, not initial roll-out, because maintenance is where most of the cost will likely be.
An exception may be a start-up where being first to market is of utmost importance.
Other rules:
Don't repeat yourself: factor out redundancy. However, redundancy is usually better than the wrong abstraction, which often happens because the future is harder to predict than most realize.
And Yagni: You Ain't Gonna Need It: Don't add features you don't yet need. However, make the design with an eye on likely needs. For example, if there's an 80% probability of a need for Feature X, make your code "friendly" to X if it's not much change versus no preparation. Maybe there's a more succinct way to say this.
1. All software can be simplified.
2. All software has bugs.
Therefore, all software can ultimately be simplified down to a single line that doesn't work.
From what I know, the "*s'" thing works mostly for plural nouns. For singular, it only applies to classical & religious names ending with "s" ("Jesus'", "Archimedes'" etc).
I am not an English native so I may be completely off. Feel free to rage :)
This is exactly what I am trying to establish to improve my bumpy English. My best guess is that the correct form is "Brooks's" because (1) "Brooks" is a singular noun ending with an "s" and (2) it is not a classic neither religious name. If you claim it should be "Brooks'" I am ok with this as long as you give me a sensible explanation.
There's not exactly a consensus these days on what is correct. Either is valid, but I generally prefer _Brooks' Law_ to _Brooks's Law_ since it looks more clean. Of course, Brook's Law is incorrect, as there is no "Brook"
Native English speaker, from England, and we were explicitly taught to use Brooks' rather than Brooks's.
However that didn't stop the Beatles from using "In an Octopus's Garden" as a song title. (Note that the song is about a single Octopus). I would suggest that it depends on whether you intend to explicitly repeat the 's' when speaking.
Plurals of words ending with an 's' are an occasional minefield. You sometimes hear people smugly insist that the plural of Octopus should be Octopi, only to have someone even more smugly point out that Octopus is from Greek, not Latin, and so it should be Octopodes. Meanwhile the rest of us just continue to use Octopuses....
I like Wiggin's Law (found in [My Heroku Values](https://gist.github.com/adamwiggins/5687294)): If it's hard, cut scope. I'm working on a compiler for my new language and sometimes I get caught up in the sheer amount of work involved in implementing a new language. I mean, I have to write a typechecker, a code generator, a runtime (including GC), a stdlib, etc. But instead of just getting overwhelmed, I'm trying to cut scope and just focus on getting a small part working. Even if the code is terrible, even if it's limited in functionality, I just need to get something working.
ReRe's Law of Repetition and Redundancy [2] seems appropriate here:
A programmer can accurately estimate the schedule for only the repeated and the redundant. Yet,
A programmer's job is to automate the repeated and the redundant. Thus,
A programmer delivering to an estimated or predictable schedule is...
Not doing their job (or is redundant).
Last week I was trying to remember a term for when a programmer designs a system so generic that it becomes a prototype of itself. For the life of me, I can't remember - anyone here on HN know?
Am I the only person here thinking that many of them are just anecdotes, or are deprecated?
> Given enough eyeballs, all bugs are shallow.
Just count of viewers doesn't help. The owners of these eyeballs need both motivation to look for these bugs, and expertise to find them.
> The power of computers per unit cost doubles every 24 month.
Slowed down years ago.
> Software gets slower faster than hardware gets faster.
It doesn't. If you'll benchmark new software on new PCs versus old software on old PCs processing same amount of data, you'll find out the new one is faster by orders of magnitude.
Input to screen latency might be 1-2 frames slower, because USB, GPU, HDMI, LCD indeed have more latency compared to COM ports, VGA, and CRT. But throughput is way better.
> Premature optimization is the root of all evil.
Was probably true while the power of computers doubled every 24 month. It doesn't any more.
I would say Postel's Law, "Be conservative in what you send, be liberal in what you accept," should be tempered a bit. Sometimes it makes sense to be a bit more liberal with what you send (to make sure that consumers can handle errors) and more strict with what you accept (to make sure that consumers aren't relying too much on undocumented behavior).
For example, if you have a service with near 100% uptime, any other service which relies on it may not be able to handle errors or unavailability. Introducing errors in a controlled way can help make the dependencies more reliable.
As another example, being liberal about what you accept can sometimes result in security flaws, since different systems might be interpreting a message differently. Rejecting malformed input can be a beautiful thing.
I know what Postel’s law is about, the argument stands. Postel said that in 1989 and our thinking about protocols has changed a bit since then. If you’re implementing a standard protocol like HTTP or TLS, and you are liberal in what you accept, this can cause security problems or other unintended behavior. For example, consider a proxy or gateway that interprets a request differently from an authoritative server. Suppose a nonstandard request is handled differently by each component. Ideally, one of the responses is, "this request is malformed, reject it". If each component handles the same request differently but without rejecting the request, you are quite possibly in a world of hurt.
More concrete example: suppose that an incoming HTTP request contains CRLFLF. To the proxy, “liberal in what you accept” might mean that this is interpreted as CRLF CRLF, which is the end of the request header. To the authoritative server, perhaps the second LF is silently discarded and ignored. Voilà: instant cache poisoning attack.
Oh please, not the Knuth's "principle" again. Optimization is a skill, it's not evil. A skilled engineer can build sufficiently good systems without wasting much extra time on optimizations.
> Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.
Premature optimization isn't bad, premature micro optimization is bad. You should also be thinking about optimization that results in better architecture and architectural decisions that make it easier to optimize in the future.
Yeah, I get frustrated that few people actually post the full quote, because, with the context, it means something completely different to young ears.
The full quote makes me think: "You should identify the critical paths of your system early." The shortened quote makes me think: "Deal with performance later."
Personally, I think it's more about balancing trade offs. You need to have some semblance of target performance needs. Bad architecture can be hard to overcome later.
Most decisions are small, but can lead to compounding effects. Personally, I think one should also avoid premature pessimissation as well. No one in their right mind would use bubble sort over quick sort, for instance (not saying quick sort is the best algorithm, but it's better than bubble sort). One pet peeve I have in C++ is when I see people initializing a std::string with a literal empty string instead of using the default constructor. The default constructor is usually a memset or initializing 3 pointers. Initializing with an empty literal involves a call to strlen, malloc and strcpy. I've yet to see a compiler optimize this. May not seem like a big deal, but considering one of the most frequently used data types is a string, it adds up a lot. Most of the applications I've worked on show std::string methods and constructors as hotspots when profiled (back office financial systems).
I agree one should avoid premature micro-optimization, but that you can also avoid premature pessimissation.
The problem with the Knuth quote is that apparently people have turned the word "premature" into a synonym for "up-front." No, that's not what it means. Knuth is not saying that you should code (shit-out) the whole system naively and then try to find out where the bottlenecks are, as this dumb post suggests. Anybody that knows about the Knuth programming contest story would know he would be the last to endorse this.
Premature literally means spending time on optimizing individual things before their need becomes apparent. It doesn't mean you should delay optimizing a system design from day 1.
I think the issue is that people often conflate optimization with simplification. You can, and should, try to simplify the problem space early on in the project life cycle but don't waste your time on things like comparing runtime performance of string pattern matching algorithms.
DevOps Borat is a wonderful, if hardly understandable, account of related 'rules' and aphorisms. Sadly, it is no longer updated: https://twitter.com/devops_borat?lang=en
Some choice tweets:
Cloud is not ready for enterprise if is not integrate with single server running Active Directory.
Fact of useless: 90% of data is not exist 2 year ago. Fact of use: 90% of data is useless.
In devops we have best minds of generation are deal with flaky VPN client.
For increase revenue we are introduce paywall between dev team and ops team.
Kind of unrelated to the article, but does the Moore's law joke about the cat constant make any sense? The `-C` constant should be on both sides of the equation (since the formula is future computation _relative to_ current computation), and thus cancel out. As it stands, the equation doesn't make sense when 'Number of years' is zero, and is inconsistent between calculating twice in 2-year intervals and calculating once with a 4-year interval (as an example).
Wouldn't the following be an embrace of Conway's Law rather than a defense against it?
> It is much better, and more and more implemented as such, to deploy teams around a bounded context. Architectures such as microservices structure their teams around service boundaries rather than siloed technical architecture partitions.
> So, structure teams to look like your target architecture, and it will be easier to achieve it. That's how you defend against Conways's law.
I expected to see Lehman's laws[0] in there too, but maybe they are not famous enough. Maybe they don't deserve to be, but I think they are relevant observations.
Also, I think Murphy’s law should be removed, it’s less true than the other laws here.
I read a fantastic article many years ago in the Atlantic where the author was analyzing and deconstructing an airplane crash, and in it was a paragraph about how Murphy’s law is completely backwards, and in reality if things can go right, then they will. Things will almost always go right unless there’s no possible way they can, in other words only the extremely rare alignment of multiple mistakes causes catastrophes. Can’t remember if the author had a name for the alternative Murphy’s law, but I believe it, especially in software. We get away with crappy software and bugs & mistakes all over the place.
I think people interpret Murphy's law incorrectly most of the time.
We can extrapolate from "Anything bad that can, happen will happen", and get the statement: "If something can physically happen, given enough time, it will eventually happen."
I like to think its sort of a very tangential sister idea of the mediocrity theory.
"Keep in mind that it is also competitive, and that if one of its purposes is to make money, the other is to move the public through thin air cheaply and at high speed. Safety is never first, and it never will be, but for obvious reasons it is a necessary part of the venture. Risk is a part too, but on the everyday level of practical compromises and small decisions—the building blocks of this ambitious enterprise—the view of risk is usually obscured. The people involved do not consciously trade safety for money or convenience, but they inevitably make a lot of bad little choices. They get away with those choices because, as Perrow says, Murphy's Law is wrong—what can go wrong usually goes right. But then one day a few of the bad little choices come together, and circumstances take an airplane down. Who, then, is really to blame?"
Of course, regardless of which way you interpret Murphy's law, the law itself and this alternative are both hyperbolic exaggerations. The main question is more of which way of looking at it is more useful.
In terms of thinking about safety, it seems like both points of view have something important to say about why paying attention to unlikely events is critical.
I suppose what I generally mean is that most of the people that I've talked to only consider it within the scope of "what can go wrong", and seem to never consider the more general statement. I'm certainly not claiming to be the first person to think such a way, if that's the impression I gave off.
Murphy's law is a favorite of mine because it's the perfect driving board for conversations about infinite probabilities and aliens and simulation stuff.
I guess I still don't know exactly what the more general statement is you're referring to. Do you mean just that a non-zero probability of a single event happening equals 100% probability given a large enough sample of events (which may take a large amount of time)?
I feel like Murphy's law as stated captures that idea adequately. And it's certainly true if the event probability really is non-zero. Sometimes, though, we can calculate event probabilities that are apparently non-zero based on known information, but are zero in reality.
One example in my head is quantum tunneling. Maybe this is along the lines you're talking about? And this is the way my physics TA described it many years ago, but caveat I'm not a physicist and I suspect there are some problems with this analogy. He said you can calculate the probability of an atom spontaneously appearing on the other side of a solid wall, and you can calculate the same (less likely) probability of two atoms going together, therefore there is a non-zero probability that a human can teleport whole through the wall. The odds are too small to expect to ever see it, but on the other hand, with the amount of matter in the universe we should expect to see small scale examples somewhat often, and we don't. There may be unknown reasons that the probability of an event is zero.
It’s also in Understanding Human Error by Sidney Dekker when talking about normalization of deviance. Everything that can go right will go right and we’ll use that to justify deviance more and more.
As I interpret Murphy's Law, it's not so much about failure in actuality, but more about anticipating the failure, and designing your code/product/system for the worst case scenario.
Murphy himself was unhappy abut the common interpretation of his law, which is negative rather than cautionary, implying a vindictiveness to exist in inanimate objects and the laws of chance.
> but more about anticipating the failure, and designing your code/product/system for the worst case scenario
Which was his intent. IIRC the phrase was coined while working on rocket sleds for a land speed record attempt. He was essentially trying to achieve "no matter what happens we want to maximise the chance of the pilot being alive afterwards, if some of the equipment survives too that is even better" and promoting a defensive always-fail-as-safely-as-possible engineering stance.
Exactly. You can't say "That won't happen" or "that's unlikely to happen". You have to have a way that handles it so that, even if it does happen, the guy on the sled doesn't die.
> Murphy himself was unhappy abut the common interpretation of his law, which is negative rather than cautionary
Are you sure about that? Murphy's actual statement was negative and not cautionary. He was criticizing a person, not saying something cautionary about the nature of the universe.
It seems to be a strange interaction between css and javascript. Using umatrix, I can read the text with both css and javascript disabled, but not with only javascript disabled. This is the first time I encounter this curious behavior.
My law: convenience topples correctness.
Evidence -programmers have been proven incapable of quoting Knuth's optimization principle correctly and in full
Well, I wonder if it is true. I mean, theoretically, something could reach 50% drop down to 30% again and double to 60% again. Yes, it is unlikely, but I see no reason why it should not be possible:
* Putt's Law: "Technology is dominated by two types of people, those who understand what they do not manage and those who manage what they do not understand."
* Putt's Corollary: "Every technical hierarchy, in time, develops a competence inversion." with incompetence being "flushed out of the lower levels" of a technocratic hierarchy, ensuring that technically competent people remain directly in charge of the actual technology while those without technical competence move into management.
In the Peter model, everyone gets (or tends to get) promoted until they reach a job they can't do, and they stay there. Thus everyone will (tend to) be incompetent. In Putt's model, the technically incompetent get promoted, and those at lower levels are competent.
Putt's does sound more like the way the world works...maybe. Peter's has always sounding convincing to me, yet the world evidently isn't so bad as that.
A partner to the Peter Principle, particularly with respect to managers, is the Dunning-Kruger effect: "In the field of psychology, the Dunning–Kruger effect is a cognitive bias in which people of low ability have illusory superiority and mistakenly assess their cognitive ability as greater than it is."
That loaded extremely slowly on mobile admittedly, but I do agree that you're being overly harsh. Why assume he authored the site himself? Is it a requirement that someone doing web programming has to author their own blog site? It feels like a form of gatekeeping to be honest.
Oh no, the problem is they DO know how to program; a simple web page (or off the shelf CMS or blog software) is too easy.
Anyway, this was made with Ghost according to the generator tag; send https://ghost.org/ a ping that you're willing to help them improve their software.
100% agree. This website looks terrible. You can't be a self-declared "web developer", contemplate poetically about meta-programming, and publish this amateurish thing. Fix the #anchors to start with?
Single page apps have quite a bit of control over rendering, however Google prefers that indexed markup be pre rendered from the server. Juggling the two competing priorities leads to byzantine technical issues.
Front end development for content sites can be complex.
No you're not being harsh. That site loads 1.3 mb of js, even though it doesn't have any dynamic content at all. The small header images for related articles you see along the right side are loaded as full hd images (probably the fault of wordpress theme).
Looks like the author has a real good internet connection and just hacked together a site over a lunch.
Web devs should really limit there internet connection to 100k while testing their sites.
We have found that by changing our software/system architecture we have also inadvertently changed our organisation structure.
- Inverse Conway Law or just Roy's Law ;-)
Before we had four cross functional teams, working on a single application, everyone felt responsible for it, worked overtime to fix bugs etc, we had good communication between the teams.
But after we switched to microservices the teams became responsible for just a part of the system, their microservice(s). Whenever we had an outage, one team was left to fix it, the others just went home. They stopped talking to each other because they didn't share any code, no issues... they stopped having lunch together, some things got way worse in the organisation, all sparked by a 'simple' architectural change, moving to microservices.