Can’t it be both? :)
Ah, fair :) then yeah, I’d say it’s pretty aligned with emerging architecture, just that I’m trying to define the values (and in the next post, technical guidelines based on those values) to (hopefully!) help you make the right decisions as you’re working on an emerging architecture.
I built my Sudoku Pi with it. iOS only still: https://apps.apple.com/nl/app/sudoku-pi/id6467504425?l=en-GB
It’s open-source: https://github.com/Couch-Chilis/sudoku-pi
I assume you're referring to this blog series: https://medium.com/prospa-technology/emerging-vs-intentional-architecture-385071ae5d75 ? I wasn't aware of it, and it seems to have some insightful observations! There's definitely some overlap, but by the looks of it, I think I will diverge quite a bit with my next post. I think I'm pretty aligned on the "One-Way Decisions" vs "Two-Way Decisions" part. A One-Way decision in my mind would be, which programming language or framework do we use? Do we use REST or GraphQL?
But it doesn't really go into how to deal with Two-Way decisions, apart from saying to trust your developers. And I think it kinda glosses over the part that things that may appear to be Two-Way decisions initially may actually be closer to One-Way decisions if you continue to build on them. So where that blog still focuses quite a bit on the process, I think I want to shift the focus a bit more to the technical side (so far I've mostly laid down the values that inform the technical direction), especially when it comes to Two-Way decisions. I wasn't thinking about covering One-Way decisions much, but rather on how to shape everyday coding to be more in alignment with Post/Emerging architecture so that you can avoid the Two-Way decisions that in retrospect aren't as much of a Two-Way decision as you'd hope.
Hope that makes sense :D
Thanks! This mirrors quite some experiences I’ve had over the years indeed. And for what it’s worth, I think the way you’re handling that is not bad at all.
As someone else mentioned in the comments on Mastodon, one of the hardest things about mentoring is articulating the lessons you may not even realize you’ve learned. I don’t think anyone can be blamed for failing to teach or convince someone else, since people are simply too different to be able to teach and convince them all. As you say, you have to pick your battles, and as long as you let your teammates do their work respectfully in their own way, that alone is a great achievement!
On the implications of defining the architecture after you build the product -- part II
After my previous post introducing Post-Architecture, I received a bunch of positive feedback, as well as enquiries from people wanting to know more. So I figured a follow-up was in order. Feel free to ask questions here as well as on Mastodon!
JSON patch is a dangerous thing to use over a network. It will allow you to change things inside array indices without knowing whether the same thing is still at that index by the time the server processes your request. That’s a recipe for race conditions.
It’s limited to JS runtimes, but this discussion might be of use: https://github.com/biomejs/biome/discussions/2467 I think you may find Boa fits your criteria, except for the JIT part.
Yeah, sorting is definitely a common use case, but note it also didn’t improve every sorting use case. Anyway, even if I’m a bit skeptical I trust the Rust team that they don’t take these decisions lightly.
But the thing that lead to my original question was: if the compiler itself uses the std sorting internally, there’s also additional reason to hope that it might have transitive performance benefits. So even if compiling the Rust compiler with this PR was actually slower, compiling again with the resulting compiler could be faster since the resulting compiler benefits from faster sorting. So yeah, fingers crossed 🤞
Yeah, it was the first line of the linked PR:
This PR replaces the sort implementations with tailor-made ones that strike a balance of run-time, compile-time and binary-size, yielding run-time and compile-time improvements.
It was also repeated a few paragraphs later that the motivation for the changes was both runtime and compile time improvements. So a little bit bumped to hear the compile time impact wasn’t as good as the authors hoped apparently. I’m not even sure I fully endorse the tradeoff, because it seems the gains, while major, only affect very select use cases, while the regressions seem to affect everyone and hurt in an area that is already perceived as a pain point. But oh well, the total regression is still minor so I guess we’ll live with it.
The post mentioned that the introduction of these new algorithms brings compile-time improvements too, so how should I see this? I assumed it meant that compiling applications that use sorting would speed up, but that seems like a meaningless improvement if overall compilation times have regressed. Or do you mean compiling the compiler has become slower?
Does the Rust compiler use their std sort algorithms, or does it already use specialized ones? If the former, it would be a great side-effect if the compiler itself receives additional speed ups because of this.
From what I understand as I skimmed over the stable sort analysis (https://github.com/Voultapher/sort-research-rs/blob/main/writeup/driftsort_introduction/text.md), it lost out against driftsort.
The System76 scheduler helps to tune for better desktop responsiveness under high load: https://github.com/pop-os/system76-scheduler I think if you use Pop!OS this may be set up out-of-the-box.
Essentially, but it doesn’t roll off the tongue as nicely 😅
I made Sudoku Pi: https://apps.apple.com/nl/app/sudoku-pi/id6467504425
Sorry, still iOS only thus far!
On the implications of defining the architecture after you build the product
This post highlights my experience working with software architecture in startup environments. I think the approach is different enough from the traditional notion of software architecture that it may warrant its own term: post-architecture.
Smart pointers are really really nice, I do recommend getting used to them (and all other features from c++11 forward).
You’re recommending him to give up his sanity and/or life?
The other day I saw a link to Verus on here and it’s made me somewhat interested in the topic how Rust and formal verification can work together.
It’s quite insightful to see how the borrow checker both required and ended up facilitating the ability to do more extensive formal verification on Rust code.
Something like Verus (I haven’t looked into most of the other tools in this space yet, there seem to be many!) does appear poised to make verification quite approachable in low-level, self-contained Rust code already, and I’m curious to see how things evolve from there.
It would be exceedingly cool if one day there’s a subset of libraries on crates.io that are fully verified (similar to how today there’s a subset that supports no-std
development) and which are then usable to build upon in your own formally verified code.
Based on the limited (but useful!) information in your profile and your age I would estimate competent mid-level fits you.
And conversely, something Go is very bad at. For example, os.Chmod
silently not doing anything on Windows.
Wow, I really like their macro syntax! That seems very approachable to someone who usually doesn’t formally verify their code :)
cross-posted from: https://programming.dev/post/12807878
> This new version provides an easy path to migrate from ESLint and Prettier. It also introduces machine-readable reports for the formatter and the linter, new linter rules, and many fixes.
This new version provides an easy path to migrate from ESLint and Prettier. It also introduces machine-readable reports for the formatter and the linter, new linter rules, and many fixes.
Rust Optimization: Vec::into_iter().collect()
I just had a random thought: a common pattern in Rust is to things such as:
rs let vec_a: Vec<String> = /* ... */; let vec_b: Vec<String> = vec_a.into_iter().filter(some_filter).collect();
Usually, we need to be aware of the fact that Iterator::collect()
allocates for the container we are collecting into. But in the snippet above, we've consumed a container of the same type. And since Rust has full ownership of the vector, in theory the memory allocated by vec_a
could be reused to store the collected results of vec_b
, meaning everything could be done in-place and no additional allocation is necessary.
It's a highly specific optimization though, so I wonder if such a thing has been implemented in the Rust compiler. Anybody who has an idea about this?
GritQL integration progress · Biome.js
It's been almost two months since I originally proposed integrating GritQL into Biome. Since then a lot has happened. And a lot more remains to be done. With this post I hope to give a little bit o...
![GritQL integration progress · biomejs biome · Discussion #2286](https://programming.dev/pictrs/image/54aa37f5-b435-423f-85d6-ea6d34c81d38.png?format=webp&thumbnail=256)
Just a progress update on a fun open-source project I'm involved with. Biome.js is a web toolchain written in Rust, and it provides a great excuse to play around with parsing technologies and other fun challenges :)
Productivity of Rust teams at Google
![](https://programming.dev/pictrs/image/7356d690-e215-45ed-949e-2d2b11594e16.jpeg?thumbnail=256&format=webp)
![](https://programming.dev/pictrs/image/7356d690-e215-45ed-949e-2d2b11594e16.jpeg?format=webp)
Slide with text: “Rust teams at Google are as productive as ones using Go, and more than twice as productive as teams using C++.”
In small print it says the data is collected over 2022 and 2023.
Unused lifetime parameter -- except it isn't
I have a fun one, where the compiler says I have an unused lifetime parameter, except it's clearly used. It feels almost like a compiler error, though I'm probably overlooking something? Who can see the mistake?
main.rs ```rs trait Context<'a> { fn name(&'a self) -> &'a str; }
type Func<'a, C: Context<'a>> = dyn Fn(C);
pub struct BuiltInFunction<'a, C: Context<'a>> { pub(crate) func: Box<Func<'a, C>>, } ```
```text
error[E0392]: parameter 'a
is never used
--> src/main.rs:7:28
|
7 | pub struct BuiltInFunction<'a, C: Context<'a>> {
| ^^ unused parameter
|
= help: consider removing 'a
, referring to it in a field, or using a marker such as PhantomData
For more information about this error, try rustc --explain E0392
.
error: could not compile lifetime-test
(bin "lifetime-test") due to 1 previous error
```
A little trick that can help make switch statements more type-safe
Today I'm sharing a little trick that I like to use to make switch statements cleaner and more type-safe. Happy to hear other ideas!
This post explores how we improved upon Bevy's out-of-the-box UI experience for our Sudoku Pi project
As part of my Sudoku Pi project, I’ve been experimenting with improving the Bevy UI experience. I’ve collected most of my thoughts on this topic in this post.
A Deep Dive Into Fiberplane's Operational Transformation
How Fiberplane Notebooks implement Operational Transformation
![A Deep Dive Into Fiberplane’s Operational Transformation - Blog](https://programming.dev/pictrs/image/010e93b2-990d-462d-8128-f1ee5fc7015f.png?format=webp&thumbnail=256)
I wrote a post about how our Operational Transfomation (OT) algorithm works at Fiberplane. OT is an algorithm that enables real-time collaboration, and I also built and designed our implementation. So if you have any questions, I'd be happy to answer them!