Dawid Ciężarkiewicz aka `dpc`

programming

TL;DR: I published a parallel processing library for Rust that works differently than rayon and is especially useful in cases where rayon falls a bit short. I'll talk a little bit about it, and show you when it can be helpful.

Read more...

I've recently purchased the Data-Oriented Programming Unlearning objects by Yehonathan Sharvit. I and would like to write out some notes I've captured during reading it.

I don't like technical/programming writing using personal narration. It just seems fluffy to me. A lot of words, with very low information density. But that's just my opinion – maybe other people enjoy it.

The book starts with a straw-man of a naive (but not uncommon to see in reality) OOP code. Then the author goes on to explain what's wrong with it. I agree with most of the critique. The core of the proposed alternative approach is to separate code from the data, which I also advocate. I actually agree with a lot of things described in the book, so from now on, I'll focus on my disagreements.

The book advocates representing all the data separated from the code as a recursively nested map of free-form objects keyed by strings. Basically, all the data is one big JSON object. And I can't agree with that.

I guess at the root of the disagreement comes dynamic vs static typing again. If you are going to use a dynamically typed language... you might as well do what the book advocates. Shove everything in JSON maps. In modern programming languages with a nice type system (Rust, Ocaml, etc.) with generics, type inference, structural pattern matching, such an approach doesn't make sense. You'd be throwing tons of benefits, for a very little benefit.

The book unsurprisingly uses JavaScript for code examples, and the author mentions coming up with DOP from a Closure background. I don't want to get too into dynamic vs static typing debate, but IMO: the way type system was implemented in legacy languages like Java is terrible, and I can't blame the industry for switching to Ruby, Python, JS, etc. eventually, but nowadays statically types languages like TypeScript, Rust, etc. are way better and static typing wins over dynamic typing.

My preference and advice: if you are in the static typing camp, ignore these untyped maps, and use types instead. A lot of other things described in the book will work with types just as well. The author mentions the disadvantages of using static types, and there's a lot of truth in it. But it does not change my opinion.

Generally while reading the book it was clear to me that the whole approach is optimized for backend request-response JSON data shoveling. My background is in implementing much more complex software, with tight performance and complexity requirements, of various types, among some usual JSON shoveling between HTTP endpoints and a database. This DOP approach is going to quickly break down when challenged by more complex (technically or socially) scenarios, IMO.

While I am an advocate of functional programming and immutability, the author severally downplays and/or ignores the downsides and limitations of immutability, persistent data structures, functional programming, etc. Yes, mutability is a sharp tool and it's best to opportunistically avoid it, but it's still a necessary and/or worthwhile tradeoff in a lot of cases.

In chapter 13: Polymorphism without objects, a multimethod approach to dynamic polymorphism was presented and it seems very clunky. In my own (very data-oriented) programming approach, I just use interfaces a lot, in the code part of my software. And if I had to implement a dynamic call based on the value of some “type” field, I would just use case statement, and I think the author is making similar mistakes as OOP developers by dismissing it.

Anyway, to sum up: the “Data-Oriented Programming Unlearning objects” is an interesting book as in so far as it breaks out of OOP dogma. It presents a complete set of ideas and tools to design and implement software avoiding OOP dogma. I don't agree with some ideas in it, in particular, abandoning the benefits of static typing by representing everything as a JSON object, but nevertheless, I think it's a worthwhile read for people looking for some food for thought and exploring alternatives to OOP.

#programming #books

I was just recently mulling over how interfaces (Java-style) for data types are pretty much always the wrong thing to do.

Putting an interface means losing a resolution on something. Now you have to talk to it through a generic approximation. The benefit of that – you can now talk to anything that implements that interface, which means an open set. Anyone can come and add a new thing that implements that interface and it will work, without changing a line of code. Drawbacks: All the additional information about that thing is lost, and you have to come up with that interface which is not a trivial task. As the business logic changes, such interfaces often need to be revised. And as any abstraction and indirection – it introduces some confusion and mental tax.

In a typical business setting, data shape type is almost always a closed set. Even if you have N versions of some you want to support, you don't expect random external developers to add more, without altering the broader code around it. The closed set of allowed formats can just be expanded, new cases handled and the job is done. And business logic is never as simple as we would like and very often requires conditional handling, which is just painful to express via interfaces. A “switch statement” is more flexible and can do whatever without bothering with defining a contract between the data and the code using it.

While there are exceptions and it is all context-dependent, as a rule of thumb, avoid stuffing your data with interfaces, and use sum types.

#oop #programming #software

This is going to be a quick overview of how I tend to write my application code. It might be a bit Rust-centric, but I apply similar methods in all programming languages I use.

I think it's an important subject and during past online discussions about learning Rust and writing code “the Rust-way”, I was asked multiple times how do I do it. I don't really have a lot of time to write something longer and better structured, so please excuse anything that is confusing. You get what you pay for.

Also, I don't want to suggest this is some sacred, best way or anything like that. I think this is what I'm typically doing. A result of years of professional and Open Source work and experiences I gained during that time. I'm always happy to learn and get to know other points of view, so I'm happy to hear any feedback.

Read more...

Code reuse in Rust

In my opinion, one of the biggest reasons why Rust is so productive is that it's a superb language for code reuse.

First, ownership and borrowing system allows exposing in the API properties that are often impossible to express in other languages. The fact that the API communicates and enforces how the resources are being created, shared and moved and destroyed, all checked at the compilation time, gives the user great confidence that they are using any API – internal or external – correctly.

Second, Rust comes with first-class built-in tooling around discovering, creating, sharing and using publicly available Open Source libraries. It's not a property unique to Rust, but it builds a powerful synergy when combined with the first point.

Third, the community (at least so far), were strongly encouraging uniformity and commonality: similar code style, similar documentation style, common core libraries, and patterns. A big chunk of this effort was achieved through great tooling like rustfmt and clippy. Thanks to this, Rust ecosystem does not feel fragmented. Jumping into a code authored by someone else does not feel like a venture into a foreign land, as it often does in other programming languages.

Together, this properties creates a language and ecosystem where code reuse is almost effortless. While in other languages it's often more tempting and more convenient to implement things yourself and avoid learning a new API, in Rust the difference between own and 3rd party code, often blurs completely. In a way, this creates a completely new quality of building your software.

Despite all these strengths, there's one problem that sticks out like a sore thumb: trust. Every additional dependency is another piece of code that could be buggy, or even malicious. And in my opinion, it's problem so serious, that is entirely blocking the untapped potential of code reuse in Rust.

Read more...

The longer I do software engineering (and even things outside of it), the more confidence I have that one of the most important metrics (most important one?) in any sort of creative process is iteration time.

What do I mean by iteration time? The time between having an idea for change and getting real feedback from the real world what are the results of implementing this idea.

Worse is Better, Agile, Lean, Antifragile they can all be destiled to iteration time.

The world is an infinitely complex place. It's very very hard to predict the real results of any action. Because of that, to navigate world it's best to make small steps and collect feedback. The faster you can make these steps, the faster you use a new knowledge, to make new, better steps, which compounds very quickly.

It's a principle so powerful, that taken to extreme allows agents that literally have no understanding of anything, beat everyone.

Read more...

Object-oriented programming is an exceptionally bad idea which could only have originated in California.

— Edsger W. Dijkstra

Maybe it's just my experience, but Object-Oriented Programming seems like a default, most common paradigm of software engineering. The one typically thought to students, featured in online material and for some reason, spontaneously applied even by people that didn't intend it.

I know how succumbing it is, and how great of an idea it seems on the surface. It took me years to break its spell, and understand clearly how horrible it is and why. Because of this perspective, I have a strong belief that it's important that people understand what is wrong with OOP, and what they should do instead.

Many people discussed problems with OOP before, and I will provide a list of my favorite articles and videos at the end of this post. Before that, I'd like to give it my own take.

Read more...

One of the things I love about Rust is its ownership-system. The ability to express a resource changing ownership (moving) is a huge enabler, eg. allowing to express APIs that are impossible to misuse.

I've just a found a good example: Bulletproofs are implemented in Rust, and are using move semantics to enforce secure usage.

As a side-note: it looks to me like Rust has already become a de facto standard for #crypto world infrastructure.

#programming #crypto

I think I've discovered Rust somewhere around the year 2012. Back then it was much different language than it is today. It had green-threads, @ and ~ were used a lot, and there was even a GC.

Rust caught my attention because I was looking for a language for myself. I always considered myself “a C guy”: a bottom-up developer, that first learned machine code, then learned higher level programming. And while C was my language of choice, I couldn't stand it anymore.

I was tired of how difficult it was to write a correct, robust software in C, especially:

  • inability to create solid abstractions and nice APIs,
  • segfaults, double checking my pointers and general lack of trust in my code,
  • make and make-likes building system.

I loved the simplicity and minimalism, I loved the flexibility and control, but I couldn't stand primitivism and lack of modern features.

With time I grew more and more fond of Rust. The language kept evolving in a direction that was my personal sweet spot: a modern C. And at some point I realized I'm in love with Rust. And I still am today, after a couple of years of using it.

Just look at my github profile. It has “Rust” written all over it. And check how my contributions grew since 2013. Rust made me much more productive and enthusiastic about programming.

So let me tell you why is Rust my darling programming language.

Read more...

TL;DR

The biggest strength of #Go, IMO, was the FAD created by the fact that it is “backed by Google”. That gave Go immediate traction and bootstrapped a decently sized ecosystem. Everybody knows about it, and have a somewhat positive attitude thinking “it’s simple, fast, and easy to learn”.

I enjoy (crude but still) static typing, compiling to native code, and most of all: native-green thread, making Go quite productive for server-side code. I just had to get used to many workarounds for lack of generics, remember about avoid all the Go landmines and ignore poor expressiveness.

My favorite thing about Go, is that it produces static, native binaries. Unlike software written in Python, getting software written in Go to actually run is always painless.

However, overall, Go is a poorly designed language full of painful archaisms. It ignores multiple great ideas from programming languages research and other PL experiences.

“Go’s simplicity is syntactic. The complexity is in semantics and runtime behavior.”

Every time I write code in Go, I get the job done, but I feel deeply disappointed.

Read more...