gbear0
I keep asking myself the same questions, and the conclusion I keep coming to is the clean modeled structure we want to see is for humans to maintain and extend, but the AI doesn't need this.
There's definitely an efficiency angle here where it's faster for AI to go from a clean modeled solution to the desired solution because it's likely been trained on cleaner code. Is this really going to matter though?
The best argument I can come up with is the clean modeled solution is better for existing development tools because it's less likely to get confused by the patch work of vibes throughout the code; but this feels like it ultimately becomes an efficiency concern as well.
This just might be the new reality, and we need to stop looking behind the curtain and accept what the wizard presents us.
Biggest challenge to me is the UX and navigating the relationships between entities (systems, components/modules, classes, functions, read/write memory, etc) requires a lot of design effort around how they work together consistently at all levels. Conceptually, your view is a set of boxes that are a filter/group-by over a lot of entities at some level, and you want to explode only some of those entities. eg. say you want to zoom into a micro-service's component level, but still see external APIs, which could be a single box per API or boxes for each endpoint. So the control you need over the way zooming works and the 'lens' over relationships filter/group-bys can easily become very complex; probably a good research project itself though!
I do think it's possible to build a good interface that would allow viewing from global cloud scale systems and right into the code through multiple paths, like design patterns/components or git repos with files/folders, but I'm not sure how nice it's going to be to use. There's a reason UML modelling didn't stick around. And I'm not sure there's enough of a business case to fund it, but I'll definitely keep hoping to see it some day.
I think the inherent compression of a specific training set into a matrix makes this more difficult cause the basis vectors likely won't contain clean representations of human ideas, but I also wonder if starting a new training set with an initialized (or fixed) matrix of human defined concepts would help align the model's weights to something that can be interpretable
Eg. Iterate through an array:
const arr = [1, 2, 3];
for (let i = 0, l = arr.length; i < l; ++i) { console.log(arr[i]) }
Let's model it differently using an iterator: const arr = [1, 2, 3];
const arrIter = arr[Symbol.iterator]();
let i = arrIter.next();
while (!i.done) {
console.log(i.value);
i = arrIter.next();
}
At this level it's still pretty obvious what's going on, but you can still see that there's a level of abstraction between an array access vs calling 'next/value', and that obfuscates what is actually happening at the computation/instruction level.If I extend this another level then I'm going to start modelling problems using an iterable and not an array/index. New requirements come in and we extend to use an async iterable. Everything still works nicely, but in some scenarios where the actual iterable is just an array, now there's a lot of extra overhead to just do an index lookup.
Using the iterator allows the code to be reused in more scenarios, but there's usually a cost to switching the lens of abstraction so that it fits into a problems modeled differently.
The ask for compensation for getting dropped before the start date should usually be an easy one for a company to accept since that shouldn't be normal operating procedures. Otherwise, they're aware that they're explicitly screwing over people and aren't serious about hiring. Now we're back at my earlier claim, and you dodged a bullet.
You don't need to be special, but you definitely shouldn't think of yourself as a cog in the machine. If you do think of yourself as a cog, or this is an offer you can't refuse, then you've already given up your bargaining power, and you are willing to accept this.
This would hopefully reduce cases where they hand out multiple offers for a single job, or at least compensate applicants due to a change from management.
# call ./runbooks/stack/update_secret.py
# could update a secret in a vault, or update it in your deployed app
./run.sh stack update_secret --env=dev --name=foo --file=secret.txt
Most of the time my python scripts are glorified CLI commands like `docker service update` that are called through subprocess, so you shouldn't need to install dependencies beyond what you'd be typing in the CLI. It's also easy to add a verbose option to print out the commands it runs so you can do it manually. # call ./runbooks/services/build.py
./run.sh services build -v
> #--- Building images ---
> #> DOCKER_BUILDKIT=1 docker build --build-arg BUILDKIT_INLINE_CACHE=1 --label "myapp" -t example-admin-ui:local "./admin-ui"
> #> DOCKER_BUILDKIT=1 docker build --build-arg BUILDKIT_INLINE_CACHE=1 --label "myapp" -t example-frontend:local "./front-end"
> #> DOCKER_BUILDKIT=1 docker build --build-arg BUILDKIT_INLINE_CACHE=1 --label "myapp" -t example-nginx:local "./nginx"
Anything that can't be automated prints out an input line that gives instructions on what to do and just waits for you to input "yes/no" # call ./runbooks/get_crash_report.py
./run.sh get_crash_report --out=./crashes/
> # Copying crashes from AWS to './crashes/
> # Manual Step: Fill out crashes spreadsheet: docs.google/example_sheet
> Continue [y/n]?
The other really nice thing with this setup is the run.sh script is able to build up --help commands that can print out what actions are available and what params they use cause it's just python argparse. Makes discovery of what to do or looking up params really quick.At this point, the only culture you need to build is one where everyone's supposed to use the run.sh scripts and not do things manually. This enforces people to fix the scripts when something changes.
YMMV, but I've found this has simplified a lot of processes for myself at least.
So what's a good health check actually report these days? Is it just about its own status, or should it include a breakdown of the status of external dependencies as part of its folded up status?
I'd prefer to see rules limiting companies from creating products in 2 consecutive/complementary components of a supply chain unless one of the products is completely open for 'swapping' out with something else. This allows companies to still benefit from vertical integration if they don't commercialize one side of things. But as you said, it's hard to draw the lines, cause you could define a supply chain in a ton of different ways.
#!/usr/bin/env node
console.log("Hello World!");For example in ubuntu you can do
sudo update-alternatives --config editor
Some programs will use the environment variable $EDITOR, so you can add this to your shell startup configs export EDITOR=vi
Or specifically for git cli you can run git config --global core.editor viI think using state machines is just a very different way of looking at code, and it does take some mind bending to think that way; but once you do, it's much easier to blend the code together the same way you'll see imperative and functional code blended together these days and not think twice about it.
Here's hopefully a more apt example: imagine wanting to have a multiple document interface (MDI) that shows a bunch of 'window' like views. Some examples of the idea are react-grid-layout, golden-layout, react-mosaic. Each window can be minimized, maximized, moved, flashed, and closed ... all with flashy animations. You could create a whole bunch of components that allow you to capture all the different states and toggle them in different components, and effectively have the MDI business logic sprinkled all through out YOUR code, not just the 'library' code. Alternatively, you could use a state machine that captures all the states in a single spot and manages that all efficiently and safely, you just call an api to trigger state changes throughout your code.
As some other comments have mentioned, this is a fundamental part of computer science. You can get by without knowing it cause you can write a bunch of ifs and state logic all over the place. If you only know how to use a hammer, ya you could still hammer a screw in. Understanding how different data structures of different patterns fit together provides you new tools to do things in different ways when appropriate. Learn how to manage complexity, not fear it, cause there's nothing dangerous about state machines. In fact, I'd argue that anyone that thinks state machines make things more complex just isn't looking at a large enough scale because state machines should make things less complex by wrapping all the complexity inside them (when used appropriately).
Here's a couple of techniques for anyone looking to do the same:
1. Look at the 'supply chain' of inputs and outputs from your problem area. Are there new inefficiencies somewhere in the stack that you can dig into and solve, and leverage your new knowledge. This could mean a whole new area of things to learn in order to investigate or solve those problems.
2. Never accept the status quo. Every time you're asked to do something else, treat that as an opportunity to find one thing that you can improve in the related systems. Here you'll learn the new system, but you'll also learn how to pick worthwhile areas for improvement.
3. Be reflective and review what you found interesting and what you didn't and dig into the ones you didn't find interesting. Ask yourself why you didn't like things; was it cause it was too difficult to pick up? was it cause you don't like people problems? was it just too big a problem to tackle? Dig in more and ask why again (like the Toyota 5 Whys). Eventually you should be able to find a problem area that you can clearly define and potentially work on to improve.
I realize these 3 techniques won't necessarily lead to 'cool tech problems', but that's kinda the point! If you can get yourself interested in solving related problem areas, you'll find you pick up a lot of useful knowledge and value that you can apply in many other areas you wouldn't have first thought of, all while always jumping between things and not getting bored!
(edit: formatting)
Also, by using non const expressions in case statements you lose the ability to have a large number of cases get mapped into a jump table. Although, I don't even know if more modern languages even support this optimization anymore since I think supporting non const case expressions is becoming the norm in a lot of languages.
Diversity CAN BE a competitive advantage if everyone else is carving out a strict path. But if everyone is extremely diverse then heterogeneity could actually be the competitive advantage, allowing a business to specialize more or take advantage of certain economies of scale etc. etc.
Also, I find that more often than not, too much diversity leads to internal conflict because ideas differ too much, which can turn into a competitive disadvantage.
However, I've since had 2 cases that make the fixed rates more understandable. 1. In order to lower mortgage payments and provide longer stability in monthly payments that I could pass on to tenants, I got a 10yr fixed rate (around 3.4%) amortized over 30 years for an investment property 2+ years ago
2. I recently had to renew my own variable mortgage and I tried to go with variable again, however my mortgage provider wouldn't give me the variable rates advertised on ratehub.ca cause they were only for new customers. It resulted in me having to go with a 5yr fixed rate with another provider cause that was the next lowest that would work for me. I wasn't happy.
BT 0 Tr 0.000000 w ET BT 44.814370 775.487087 Td [(\0S\0e\0r\0v\0i\0c\0e)] TJ ETI found it extremely annoying at first cause I was trying to copy/paste the stream chunks around and it wouldn't copy anything after the fist null. Then I realized this was probably a security hack in the hopes that people couldn't copy the data around (I can't think of any other reason to add these nulls like this otherwise). Funny enough, I opened the PDF in chrome and copy/paste of the selected text works fine. So clearly some readers strip these bad characters, but I can imagine others might not.
But even if you could manually control the device, I'd be too afraid of having Amazon capturing full video of all my belongings. They have the resources to easily hook up the feed to an object detection ETL or some other AI system to extract a ton of information about the owners, and then sell that as specialized advertising intelligence. All of a sudden my mailbox fills up with lots of high focused ads.
OK I realize that's probably going down the conspiracy theory path a little much :), but I don't think it's too far off.
In fact this scheme is already supported with cargo since you can specify the registry per dep. This means the default registry, if nothing is added is 'crates.io/' but you can specify any other registry, eg 'gitlab.local/looks/like/namespace' for personal CI, or even 'crates.io/{username}'
Let's give each user their own registry at 'crates.io/{username}'. This works in a backwards compatible way cause registry:'crates.io/' + crate:'mypackage' is different than registry:'crates.io/mypackage' + crate:'mypackage', so nothing changes with the current crates and it's all an incremental implementation detail for crates.io
Now we have the npm user style namespace ids that lessens the namesquatting problem, but increases the security issues if the registry changes hands. Honestly, I've never really understood the security argument here cause there's no reason an owner can't hand over a single package. As well, there's no reason a currently trusted owner can't patch update a package with bad code. This is a social problem that has no solution and is the same for both naming systems, so we need to come up with another way of handling things. Personally I think all published crates should be immutable and all deps should be pegged, not even allowing patches. But this leads to the argument that sometimes publishers really do want to take down a crate. I'm on the fence with this one, so let's try to solve it in another way.
So the problem is we need to potentially remap any (transitive) dependency to something else, and since we still have a flat hierarchy we really just need to remap the registry for that dependency. So let's add a registry remapping section for the cargo deps ... wait cargo already has something for that (https://doc.rust-lang.org/cargo/reference/source-replacement...). (Reading through the docs here, it does seems like it might be a little strict on whether we can use it for this case, but it's pretty close.)
OK wrapping up, it looks like we could have backwards compatible namespaces right now if crates.io would just implement user specific registries, ie it's an implementation detail. And the security issues are really no different than before. Thus I've got to ask, what am I missing?
I wonder if instead of an OS solution we can just add more metadata to the actual binary files we compile. For example, if we have a new ELF format that has an optional list of commands, options, full input/output types, etc, any one of the shells can start to provide better tooling. Output format types can then be passed along with the stream, and potentially checked that they work as the proper inputs for another command. Let the shell auto generate the simple cli help docs, or generate the bash completions, or figure out how to better convert data to desired types.
However, there is a major value hooks provide over class components and that's the composability of the lifecycle effects. The problem with class components is that code for a lifecycle is broken across multiple functions and interweaved with other effects. This happens because the declarative model of the component tree clashes with the imperative ordering we code up for lifecycle functions attached 'within' each class component. The fix is to turn lifecycle effects into first level declarative concepts themselves (like in hooks) so they're not 'within' the component, instead they're more of a has-a relationship.
This would actually be rather simple to do, drop the lifecycle methods in a component, and add a new Component.addEffect function (or, cause I'm a big fan of decorators, you could have some decorator to declare what effects should be used). And each effect would be another class that inherits from Effect. I think the hardest part to think about is how you interweave the effects like people do in hooks as one output becomes the input for another, but I think this is probably the wrong way to think about it. Instead if you think of it as an Effect tree then each Effect is just a 'render' function where you're passing in other effects as the props and the output is passed down the tree, so you'd just need an inline effect function that would compose 2 effects together the same way we do with components. At this point the conceptual model is extremely easy cause it's declarative trees all the way down!
RootComponent
|- ComponentA
|- effects
||- lambda effect -- myClickEffect
|| |- myStateEffect
||- lambda effect -- myKeyEffect
|| |- myStateEffect
||- myCleanupEffect
|- children
|- ComponentB
|- effects
|- children
|- ComponentC
|- effects
|- children
...
Anyone wanna pass this idea onto the react team that'd be awesome cause I'd love to see this added for Class components to make them more composable as well as having better sharing of ideas between hooks and class components :)