The engineering question is what layer is it appropriate to do so. Under traditional OOP (your pre functional forward Java/C#/OOP C++), the answer was that code is almost always bound to data.
Haskell style functional programming binds code to data at the last moment possible.
The best answer is likely somewhere in the middle, depending on your application and usage. I find, for example, that UI controls work well with OOP, but most other stuff I tend to default to functional style programming.
Microservices require every action you take be a message and enforce that messages are the only way to communicate which makes it easier to avoid indirect (and thus hard to track) dependencies.
For instance if the person's age is updated when you calculate their hours worked, in OO that might be hidden from view but in message passing you would at least see that a new person object came back that replaced the one you had.
None of this stops you from doing evil unobvious things with your hidden information (updating everyones age whenever anyone gets overtime) but it is usually harder to accidentally do that.
To be clear while I like microservices I think they have many problems just like OO. For instances caching becomes super complicated and there is a real cost of going over the network for everything you do. The tradeoffs are just a different set of tradeoffs.
Though when a microservice mutates something, it's typically persisted in a database or similar (and, you'd hope, not sprinkled throughout its code). But, yeah, a bunch of communicating microservices are a lot like communicating objects - for better or worse. Same with Erlang-style actors.