I have used both and I personally think those calls are the best security mitigations in our field :)
I would love to see something as simple in Linux.
51–60 of 82 posts
I have used both and I personally think those calls are the best security mitigations in our field :)
I would love to see something as simple in Linux.
It’s probably over the top, although I respect the intent. The quickest way to destroy “velocity” is by introducing dependencies between implementation details with no barriers in code. The more constraints you have to satisfy when you make changes, the more effort it is to make the changes (provably); and thus, the more time it takes, destroying velocity. That said, doing this as described is probably overly dramati…
Do you mean that if the constraints are visible when you change the code, it's better? But "hidden" constraints which will manifest only under specific conditions under runtime are bad.
Abstractly:
A constraint is an invariant that must be true before and after the change.
It doesn't matter if they are 'hidden' or 'visible'; if you must maintain the existing behavior, then you have to prove that no constraints are violated by the change you make.
The effort you have to expend is proportional to the number of places where you have invariant that must be maintained.
However.
If you isolate constraints in groups (call them crates, modules, whatever you want), then you can create a region which has no constraints except at the boundary where you interact with a defined API.
Since the volume is always >= the surface, you can prove that having the boundary is strictly Concretely:
If you can prove (because it is impossible due to the compiler rules or whatever manual process) that you have no dependencies on the internal functions inside a particular namespace / module / etc. because the only way it is ever possible to call those functions is via a specific public API.
...then you are not constrained in changing / refactoring / removing / whatever you want.
The internal workings have no external dependencies, no callers.
It is therefore less effort to maintain that code; because any change does not require you to go hunting around for someone calling helpers.internal.finance.convertCurrency for it's view model in a completely different domain.
If you want to call that 'hidden' then sure.
I'd probably say 'different view', but if basically yes, the point is that of the entire set of constraints for the system, you can say, today, our work is in this area of the code and we have a much much smaller set of things we have to worry about while we make changes here.
It's not rocket science; you see people doing this all the time; 'It's just a few tests, it can't break the database'.
Correct. The tests are a separate package that strictly the database schema has no dependencies on.
Therefore it is quick and easy and safe to make changes to them.
...
If your project only has two domains; 'tests' and 'non-tests', you literally doing the same thing the OP is suggesting, just at a slightly reduced scale.
In bigger, more sophisticated projects, the number of mini-domains inside a single project is usually > 2; but for exactly the same reasons.
How is this different from using access modifiers (public, private, protected)? P.S: I do work with code (reading, writing and breaking it), but I’m not a software engineer.
I think the general concept here is putting in place restrictions on what code can do in service of making software more reliable and maintainable. The analogy I like to use is construction. If buildings were built like software, you'd see things like a light switch in the penthouse accidentally flushing a toilet in the basement. Bugs like that don't typically happen in construction because the laws of physics impose…
[1] https://hackage.haskell.org/package/bluefin-0.0.6.1/docs/Blu...
It’s probably over the top, although I respect the intent. The quickest way to destroy “velocity” is by introducing dependencies between implementation details with no barriers in code. The more constraints you have to satisfy when you make changes, the more effort it is to make the changes (provably); and thus, the more time it takes, destroying velocity. That said, doing this as described is probably overly dramati…
modules? crates??? uhmm... namespaces??? I think you're conflating the language design stuff with the tooling (packaging, and calling that 'modules') ....to be fair, you're conflating but I'm fanboying python in any case, the point being there's a distinction between an linker and a compiler but not in interpreted languages. so comparing rust's crates with JS, python (even java) is an instance of apples-to-oranges co…
Ironically, untyped languages like js and python are particularly prone to the problems from poor unstructured code, because you can't use static type checking to find broken dependencies at compile time.
/shrug
Sounds similar to capabilities: https://en.wikipedia.org/wiki/Capability-based_security
Capabilities is what you get if you keep traveling down this road, deal with the resulting issues, tune the approach, and iterate on it a lot. It doesn't take long to figure out that partitioning permissions by "what functions can be called" is a nice start, and I don't mean to criticize it as a start, but it is only a start. It isn't the correct dimension of the code to cut on. Capabilities is, in my opinion, the bi…
I've worked like this for decades. Layers, with each layer assigned a particular domain and API restriction (for example, I have a multi-layer backend, and, if I want to access the database directly, I need to implement that at the very lowest layer, and then set up a "tunnel" of access to the top-layer exposed API, through the intervening layers, applying whatever access control and filters are appropriate for each…
I love how the comments are split along the lines of, "wait, some people don't do this?" and "this is a maintenance nightmare!" If you know, you know.
Yeah, it's a pain to maintain, but it is damn secure.
I think the general concept here is putting in place restrictions on what code can do in service of making software more reliable and maintainable. The analogy I like to use is construction. If buildings were built like software, you'd see things like a light switch in the penthouse accidentally flushing a toilet in the basement. Bugs like that don't typically happen in construction because the laws of physics impose…
An office was experiencing random Internet outages and they were struggling to figure out why. They traced it back to their router rebooting randomly. Tracing it back further, they found the outlet was experiencing big voltage drops. They then realized it was on the same circuit as a pump used to flush a porta potty for a construction team onsite. Everytime they'd flush the toilet, the router would lose power and reboot.