Hacker Newsnew | past | comments | ask | show | jobs | submit | blandflakes's commentslogin

> Simple, although I only mentioned repos should be mono, I should've also said deployment should be mono as well. I thought that was a given.

Deploying your service graph as one atomic unit is not a given, and not necessarily even the best idea - you need to be able to roll back an individual service unless you have very small changes between versions, which means that even if they were rolled out atomically, you still run the risk of mixed versions sets.


>Deploying your service graph as one atomic unit is not a given,

It's not a given because you didn't make it a given.

>and not necessarily even the best idea - you need to be able to roll back an individual service unless you have very small changes between versions, which means that even if they were rolled out atomically, you still run the risk of mixed versions sets.

It is the best idea. This should be the standard. And nothing prevents you from rolling back an individual service. You can still do that. And you can still do individual deploys too. But these are just for patch ups.

When you roll back an individual service your entire system is no longer in a valid state. It's in an interim state of repair. You need to fix your changes in the monorepo and monodeploy again. A successful monodeploy ensures that the finished deploy is devoid of a common class of errors.

Monodeploy should be the gold standard, and individual deploys and roll backs are reserved for emergencies.


> It is the best idea. This should be the standard. And nothing prevents you from rolling back an individual service. You can still do that. And you can still do individual deploys too. But these are just for patch ups.

There are a ton of reasons it's not the best idea. This flies in the face of a lot of _better_ ideas.

Keeping changesets small so that it's easier to debug when something goes wrong? Blown out of the water by deploying everything at once.

Bringing every service up at once is a great way to create the coldest version of your entire product.

Requiring a monodeployment turns canarying or A/B testing entire classes of changes into a blocking rollout where any other feature work has to move at the pace of the slowest change.

> When you roll back an individual service your entire system is no longer in a valid state. It's in an interim state of repair.

The gold standard is that each version of your service can work with each other version of your service, because in The Real World your service will spend time in those states.

> Monodeploy should be the gold standard, and individual deploys and roll backs are reserved for emergencies.

No, because if it's still possible to mix versions in your services, then a monodeploy doesn't actually solve any issues.

I actually am a big fan of fewer services and deploying bigger artifacts, but if you have multiple services, you have to act like you have multiple services.


>Keeping changesets small so that it's easier to debug when something goes wrong? Blown out of the water by deploying everything at once.

The size of your monodeploy is orthoganol to the concept of monodeploy. You can make a large change or a small change.

In fact your deploy can be smart. For a specific service in a full system monodeploy when upgrading from v2 to v3 it can do some sort of diff on the source of a specific service and if there's no difference it goes from v2 -> v3 without a new build and uses the same artifact from v2 to v3. The entire point is though that this service (or the entire system) still goes from v2 to v3 and it tagged this way. This is an optional optimization for speed.

In fact, your compiler when building artifacts ALREADY does this. It caches huge parts of the build and reuses it. A deploy can do the same.

This is the important concept of a monodeploy: The static check; The integration testing. The verification of the ENTIRE system as a whole. Your monodeploy determines what new artifacts need to be recreated, what artifacts need to be reused... verifies everything, and deploys.

>Requiring a monodeployment turns canarying or A/B testing entire classes of changes into a blocking rollout where any other feature work has to move at the pace of the slowest change.

Again orthoganol. Your complaining that a monodeploy is slow. Integration testing and unit testing are also slow and take time. The monodeploy is for safety. If you're saying speed > safety, here's an idea: throw all testing out the window as well. That's a big speed up right there.

If your monodeploy is slow, work on speeding it up. Work on it being smarter and faster. Do you throw testing out the window because it's slow or do you work on speeding it up? Make the smart choice.

>The gold standard is that each version of your service can work with each other version of your service, because in The Real World your service will spend time in those states.

And that gold standard is stupid. We can do better. We can go to a state where different versions between different services don't exist. Only one monoversion. You throw that concept of different versions out the window then you also throw the possibility of a mismatch out the window as well.

You're trying to deal with an error. I'm saying make the error not exist.

>No, because if it's still possible to mix versions in your services, then a monodeploy doesn't actually solve any issues.

It's not possible to mix versions in a monodeploy because the whole concept of it is to have ONE version of everything. Let me be clear I'm talking about a MONOREPO + MONOBUILD + MONODEPLOY. If there's only one version of everything and it's all deployed than issues are solved under this model. At this point I think you just don't like being wrong.

>I actually am a big fan of fewer services and deploying bigger artifacts, but if you have multiple services, you have to act like you have multiple services.

A monodeploy doesn't preclude multiple services. You can still act like it's different services. A monodeploy + monorepo just makes sure there's ONE version of the entire system.

You're solution here is just saying you want to be able to deploy different versions of different services in a staggered way. You want different repos so different modules of the system can move out of step with everything else. Service A is at v23, Service B is at v32.

The only way to deal with this mismatch is to have complicated "versioning" system on top of that where API contracts between services only accept "backward compatible" changes. This works but it's also extra complication and extra restriction. You can no longer radically change an API because it can break a number of systems in different repos. You're stuck. Or if you're willing to deal with the fallout you can make breaking changes and accept the risk whilst under my system the risk doesn't even exist.

You are advocating for an idea that's definitively worse. But you'll never admit it, not right now anyway because basically you've dug your heals into the ground. At this point I've never seen a human who is so unbiased they are capable of proper reasoning to flip their stance. If we continue talking, you will continue to build logical scaffolding to support YOUR point rather then to support A point and it's pointless (punintended) to keep going.

I'm ok to keep going, but I think it's completely obvious to any neutral arbiter that the conversation is over and that your perspective is rationally worse.


> First put all your services in a monorepo have it all build as one under CI. That’s a static check across the entire system.

There are definitely benefits to this approach. My coworkers do fall into the trap of assuming that all the services will be deployed simultaneously, which is not something you can really guarantee (especially if you have to roll one of them back at some point), so the monorepo approach gives them confidence in some breaking changes that it shouldn't (like adding a new required field).


I mean you talk about it as if it's a "benefit"

I'm talking about it in the same sense as the "benefit" of using typescript over javascript. Not just a "benefit" but it's the obvious path, the obvious better way.

Everything about monorepos and polyrepos are basically mostly just debates about opinions and styles and preferences. But most people don't understand... the monorepo is definitively better. Don't think of it as a benefit, this makes that style of error literally impossible to occur.


Well, no, it doesn't. A monorepo does nothing to prevent you from making breaking changes, it just stops you from making changes that don't compile/test. You still have to understand that services aren't deploying as an atomic unit and make sure that your network calls are forward and backward compatible.

I never said it stops you from making ALL breaking changes. But it makes a whole class of very common breaking changes Impossible to occur. This is a definitive benefit. Monorepo means much less errors, Polyrepo means more, every other difference between the two is a debatable opinion but this is definitive.

>You still have to understand that services aren't deploying as an atomic unit and make sure that your network calls are forward and backward compatible.

The time between inception of a deploy and the termination of a successful deploy isn't solved. But a monodeploy solves an entire class of errors outside the boundary of an atomic deploy. Think about what's in that boundary and what's outside of that boundary? How long does a deploy take? An hour? How long are you not deploying?

That's they key, static checking can't fix everything and a monodeploy isn't a full guarantee of safety, but it does guarantee the impossibility of a huge class of errors in the interim time between successful monodeploys.


Yeah, I think you're preaching to the choir about static checking, the only point I was making is that monorepo doesn't solve some classes of errors and that I've actually seen it generate false confidence in that realm.

Agreed. You're right it doesn't solve some classes of errors.

I guess my point is, monorepo vs. polyrepo... monorepo is the winner because it solves more classes of errors.


Go seems to have some enduring affection and popularity for new projects and companies. I recently felt like a lot of the recent shift was less about GC and more about runtime characteristics (static binaries, lean resource consumption, lack of an in-your-face virtual machine).

It never felt like Nim, Pony, or Crystal were ever that popular that a diminished hype cycle registered as something thematic to me (not that I really intend to disagree with your perspective here).


If you have to ask an object what its type is, you're probably about to cast it, and these are operations that the language doesn't enforce that you do together (and so the habit of casting can lead to the habit of casting without the check...). There are times when it's appropriate but generally if you have to ask what type an object is, your code is already starting to smell (because typically dispatching on type is handled by polymorphism, not be the programmer manually implementing it).


This isn't a personal website.


It's also pretty insulting to assume that everything is equally easy for all people.


No one is assuming that. Everyone has their burdens. But gradual improvement is always possible.


Your prior comment makes it sound like you assume it’s generally just about willpower and that external factors aren’t generally an issue. Is that accurate?


No, is generally about discipline and building good habits. Willpower or lack thereof is largely irrelevant. I'm not convinced that willpower is even a real thing.


What do you think discipline is if not willpower? This might explain why we're talking past each other.

I can do the exact same thing a hundred days in a row as long as the circumstances happen to be the same. And I can try to make them as similar as I possibly can. My lights come on at the same time. I eat the same food. My clothes are in the same place.

But the second something happens that I can't control, the night the wind howls all night, or a cough wakes me up, or for some damn reason, I wake up hungrier than normal, it doesn't matter how many times I've done it. None of it is automatic. It's all new now. All of it requires decisions. It's like it was never there. And that's why, frankly, I don't ever get to 100 identical days.

Your brain does something different with whatever you mean by "discipline and good habits" than my brain does. And that's really cool. It sounds awesome to have a brain that does that.

It also sounds way easier and like it's not something you actually deserve any credit for, in the same way that my learning how to speak before I was a year old or read before I was 3 is just "a cool thing about my brain" and not something I deserve credit for.

The difference is that because your cool thing about your brain is common, people who don't have it are considered "less than" by people who do, whereas my cool thing about my brain is uncommon, so people looked at me as "more than" other people. Both are baseless. You and I have no more control over having these advantages in our brains than we do over our height or the color of our eyes.


Willpower is making a choice in the moment. Discipline is removing the choice.


This doesn't answer the question on any level. There is ALWAYS a choice. Where does the choice go when you remove it? What exists in its stead? How is there ever not a choice?


That belongs on the wall in a CrossFit gym. It doesn’t actually mean anything.


Dicipline and the ability to build good habits is out of the window for a lot of people due to different illnesses. You come across as trying to sell snake oil to people with a heart attack.


If you try hard enough you can always find a plausible sounding excuse for failure. Discipline and good habits are the most effective way to prevent heart attacks in the first place. While there are a tiny fraction of people with serious mental health conditions or developmental disabilities which prevent them from making progress, that hardly applies to anyone on HN.


No one is arguing efficacy. We’re talking about how overly simplistic “just do it” is. Life isn’t a Nike commercial.


Yes, prevents heart attack, but if you are in the middle of one?

>that hardly applies to anyone on HN.

Sweet summer child.


This all just sounds like bootstraps by another name


Agreed; I don't actually even care about emulating this particular hardware, but these reports are just interesting reading.


They also encourage/enable code that is less testable. If you use mockito to get your fake responses/assertions where you need them, you don't have to think about your class's dependencies to make your code testable and therefore better decomposed. I don't even do TDD, but I still find that thinking about how I'd test a class guides me toward better-factored code.


One alternative to make code with typing styles in the Java way (as opposed to the Typescript or Go way) is to have a whole lot of custom interfaces and then you end up with a whole bunch of:

  doTheThing(foo: Fooable) { ... }
when there's really only one Foo implementation in prod. It leads to (what feels like, to me) more code obfuscation in large projects, than the benefits that come out, at least for me.

So Mockito and friends are a nice alternative to that.

That is just my experience and opinion though, and there are definitely more valid or equally valid alternatives.


I don't think we have to choose. Naturally finding the "right division of labor" is as infinite as finding the "right level of abstraction", but I think the ideal situation is to strive toward code that is easy to test without having to introduce a lot of mocks or without infinite layers of abstraction.


Elsewhere in this thread, dynamic typing advocates malign the hassle of maintaining types, and it is always coupled with strong advocacy for an entire class of unit tests I don't have to write in statically typed languages.


And that's the problem, if you want your code to actually work you do need to write those unit tests. A program not crashing doesn't mean it does the right thing.

With experience you will learn to either write unit tests or spend the same amount of time doing manual testing.

Once you start doing that then the unit tests just replace the static typing and you start shipping better code to your customers.


This always feels like a bad faith argument. Nobody says that with static types, you don't need any unit tests.

And your suggestion that people who like static types "don't know how to write unit tests" is further bad faith.

Perhaps it's dynamic typing programmers who don't know how to write sound programs? Except I'm not making that claim, because I'm giving you all some benefit of the doubt, a degree of respect you are not giving others.


Static typing doesn't have much value if there are proper unit tests. So it's fairly obvious that if people think there is value in static typing then they are shipping broken code to their customers.

It's called ratting yourself out.


> Static typing doesn't have much value if there are proper unit tests

Wasteful unit tests that assert your types are right don't have much value if there is a proper type system.

> It's called ratting yourself out.

Quit being childish.


"Wasteful unit tests that assert your types are right"

You don't test whether the types are right, you test if your code actually does the right thing. That's what's important to your customers.

The types getting tested is incidental.


I still haven't managed to get around to her scifi (but plan to!); but can wholeheartedly endorse The Raven Tower.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: