|
|
Subscribe / Log in / New account

Packaging Rust for Fedora

Packaging Rust for Fedora

Posted Oct 30, 2022 1:53 UTC (Sun) by dvdeug (guest, #10998)
In reply to: Packaging Rust for Fedora by tchernobog
Parent article: Packaging Rust for Fedora

> > Rust doesn't even support separating interface from implementation,

> Which is only needed in languages designed in the '70s - '80s, like C?

I'd say separating interface from implementation is needed in every large enough program, at least conceptually. C doesn't do it great; the .h file doesn't stop all symbols from leaking all over the place, and has only hacky ways of hiding information (you can't have a struct without making the details available, though you can have a pointer to a struct without the details for a struct.) Java gets away with it because class files carry the interface information and prohibit abuse of implementation details (at a computer level) and JavaDoc shows just the implementation.

I'm not that familiar with Rust, but I'd say a good language for software engineering needs at least a JavaDoc substitute (for humans) and some effort to keep users from accidentally using implementation details, if it's not going to separate interface from implementation in code. I don't know why everyone has gone away from separate interfaces, but I don't think it's been a good decision.


to post comments

Packaging Rust for Fedora

Posted Oct 30, 2022 10:22 UTC (Sun) by ssokolow (guest, #94568) [Link] (7 responses)

They've certainly got the former. Rust's JavaDoc equivalent is unadventurously called rustdoc, it's installed as part of the base toolchain, it doesn't require you to manually opt into documenting things like Sphinx for Python does, you can generate and view docs for your entire dependency tree locally with cargo doc --open, and every crate that's published to crates.io automatically gets rustdoc run on it and the result hosted publicly at docs.rs. (Though the docs.rs run is configured to only display the README for binary/non-library crates, unlike cargo doc.)

As for the latter, I don't know what your requirements are, but they certainly make a strong effort. Things like type inference are only allowed inside functions, with function signatures, consts, and statics requiring that you explicitly write out the type signature and structs even requiring you to write out lifetime annotations in places where they could be inferred. There are no exceptions, instead requiring that you declare error paths intended to be recoverable (i.e. not asserts) as part of your return type via Result<T, E>. There's no such thing as "is this class POD?" (You ask for dynamic dispatch by taking a (data, vtable) fat pointer to the object). There are various language features such as method overloading where part of the reason they don't exist is "the interaction with type inference would leak implementation details into the ABI stability characteristics". etc. etc. etc.

The ecosystem has also produced crates like static_assertions (#1 most popular crate in the #compile-time category according to the libs.rs alternative crates.io frontend), which makes it easy to fail the build if invariants like "these two types must have the same alignment requirement" get broken.

Packaging Rust for Fedora

Posted Oct 30, 2022 11:07 UTC (Sun) by ssokolow (guest, #94568) [Link]

"the interaction with type inference would leak implementation details into the ABI stability characteristics"
I keep forgetting not to post in the middle of the night. I meant "API" here.

Packaging Rust for Fedora

Posted Oct 31, 2022 0:41 UTC (Mon) by tialaramex (subscriber, #21167) [Link] (2 responses)

> function signatures, consts, and statics requiring that you explicitly write out the type signature and structs even requiring you to write out lifetime annotations in places where they could be inferred.

Lifetime elision has been enabled in Rust for some time. For example, suppose our function takes a &str and it returns a &str. We could ask, what is the lifetime of these two &strs ? But it doesn't take a genius to guess that they should probably have the same lifetime, whatever that is. The compiler will try that and, if it works, accept the function despite it not specifying the lifetimes.

https://doc.rust-lang.org/reference/lifetime-elision.html

Packaging Rust for Fedora

Posted Oct 31, 2022 1:03 UTC (Mon) by ssokolow (guest, #94568) [Link] (1 responses)

I've been using Rust since 1.0. I know what lifetime elision is. Maybe my phrasing wasn't clear enough that the "even requiring you to write out lifetime annotations in places where they could be inferred" was scoped to the "and structs", not the entire sentence.

I was referring to how, yes, you can elide lifetimes in function signatures, but you'll get a "missing lifetime specifier" error if you try to do something like this:

struct Thing {
    inner: &str,
}
When lifetime elision was implemented, stopping there was a conscious decision.

Packaging Rust for Fedora

Posted Nov 1, 2022 8:28 UTC (Tue) by tialaramex (subscriber, #21167) [Link]

Oh! Now you point it out I think my brain skipped over the "and structs". Sorry.

Packaging Rust for Fedora

Posted Oct 31, 2022 3:36 UTC (Mon) by pabs (subscriber, #43278) [Link] (2 responses)

Is there a recommended way for Rust crates to generate manual pages for command-line tools? The ones I've seen just use help2man to generate a manual page, commit that to git and maybe update it, maybe not.

Packaging Rust for Fedora

Posted Oct 31, 2022 11:28 UTC (Mon) by neal (subscriber, #7439) [Link] (1 responses)

In Sequoia, we started generating man pages from the clap data structures. It works much better than help2man.

Packaging Rust for Fedora

Posted Oct 31, 2022 12:35 UTC (Mon) by pabs (subscriber, #43278) [Link]

Interesting, thanks. As it happens and perhaps as you guessed, I was complaining here about the Sequoia keyring linter, which still does the help2man approach. Would you like a new issue as a reminder? :)

Packaging Rust for Fedora

Posted Oct 30, 2022 13:03 UTC (Sun) by emk (subscriber, #1128) [Link]

> I'm not that familiar with Rust, but I'd say a good language for software engineering needs at least... some effort to keep users from accidentally using implementation details

Rust uses namespaces with the ability to control what gets exported. If it's not exported, you can't access it. You can even say things like "this interface is visible outside of this file, but only inside of this library" (aka "pub(crate)"), or you can export certain symbols only in test mode. Private members of structs are completely hidden, and don't even lie at a predictable offset within the struct. A number of other features, like the orphan rule and trait member visibility, are designed specifically to prevent weird surprises. But Rust doesn't implement this using header files; it's built directly into the language.

Rust libraries are almost precisely limited to what appears in the documentation. And as other posters have noted, Rust's doc tools are solid. By default, if you put sample code in the docs, Rust even compiles and runs it as a unit test. (You can mark individual code snippets "no_run", which will cause Rust to only compile them.)

Packaging Rust for Fedora

Posted Oct 30, 2022 17:01 UTC (Sun) by khim (subscriber, #9252) [Link] (17 responses)

> I don't know why everyone has gone away from separate interfaces, but I don't think it's been a good decision.

It was absolutely good decision because it's bad idea to ask people to do things which computers can do better.

You never need implementation part alone, that's just never usable for anything. You need interface and implementation if you are developing library and you need just the interface if you are using that library.

And it makes much more sense for the computer to take the whole thing and remove implementation (like both Javadoc and rustdoc are doing) then to ask human to mentally combine them when s/he tries to do development.

Packaging Rust for Fedora

Posted Oct 30, 2022 19:30 UTC (Sun) by dvdeug (guest, #10998) [Link] (16 responses)

Java has "interfaces", which are different from the type of interfaces we're talking about, but can be used to separate interface from implementation. And many people online ask if every class should have an interface; among other things, that makes the object mockable.

In semver terms, the interface can not be touched in a patch level change, it can be added to but what was there can't be changed, and it can be arbitrarily changed in a major release. Even internally, the interface can't be unilaterally changed without touching other files.

Mixing interface and implementation makes it harder for the programmer to see what changes are breaking the interface. Making the interface into the implementation is usually a copy command and a few minor edits, and the computer could easily keep them compatible. Either way, the computer can help the issue, but I've seen nothing that highlights interface changes or otherwise makes them obvious to the programmer.

Packaging Rust for Fedora

Posted Oct 30, 2022 20:34 UTC (Sun) by khim (subscriber, #9252) [Link] (14 responses)

> Java has "interfaces", which are different from the type of interfaces we're talking about, but can be used to separate interface from implementation.

Not perfectly. Default implementation of methods for these interfaces (like with Rust analogue) goes in the file where interface is described.

And you can add classes to them, too:

interface MyInterface {
    void interface_not_implementation();
    static class MyImplementation implements MyInterface {
       public void interface_not_implementation() {
           System.out.println("Someone talks about separation?");
       }
    }
}
> And many people online ask if every class should have an interface; among other things, that makes the object mockable.

Yes. That what I hate about Java most. Not about Java-the-language, but about Java-the-ecosystem. Useless pile of abstractions where the actual code is very hard to find.

Why would you make every class mockable? What's the point? What are you trying to achieve? There are no implementation inheritance in Rust which means 90% of problems which this total mocking is supposed to fix just don't exist!

Traits are a bit harder to abuse for that, but, more importantly, Rust doesn't consider blind cargo-culting a viable way to write code.

> Mixing interface and implementation makes it harder for the programmer to see what changes are breaking the interface.

Maybe if you randomly change your code. Yes, trait definition goes into the same file as it's implemntation, usually, but in practice it's not hard to notice whether change is modifying trait or only it's implementation (just look for impl keyword).

> Either way, the computer can help the issue, but I've seen nothing that highlights interface changes or otherwise makes them obvious to the programmer.

It's same in Java. If you replace Object with T then it's backward-compatible change as easily can be seen, but nothing highlight that AFAICS. Same as with C or Rust: you have to look on the change to understand whether it's backward-compatible or not.

Packaging Rust for Fedora

Posted Oct 30, 2022 20:47 UTC (Sun) by mpr22 (subscriber, #60784) [Link] (13 responses)

> Why would you make every class mockable? What's the point? What are you trying to achieve?

If every class is mockable, then a unit test of class Fred can use mocks of any classes that class Fred invokes.

This is highly attractive for some people.

Packaging Rust for Fedora

Posted Oct 30, 2022 21:33 UTC (Sun) by khim (subscriber, #9252) [Link] (12 responses)

> This is highly attractive for some people.

That's not the answer why they like to compulsively mock everything endlessly.

If someone likes to get drunk it's not a good reason to make alcohol more easily available to him (or her).

Note that C doesn't allow you to easily mock something and yet Linux kernel is more reliable than creations of these guys who praise Java for the easy mockability of everything.

Which means mockability doesn't translate into higher reliability.

If people do understand why they need to mock everything religiously (and that still doesn't help entirely) then it would be easy for them to see why they don't need that in Rust.

If they don't understand where and why that cargo-cult started then I don't see why we need to even help them.

P.S. Hint: it starts with L and includes the name.

Packaging Rust for Fedora

Posted Oct 30, 2022 22:54 UTC (Sun) by dvdeug (guest, #10998) [Link] (11 responses)

> Note that C doesn't allow you to easily mock something and yet Linux kernel is more reliable than creations of these guys who praise Java for the easy mockability of everything.

> Which means mockability doesn't translate into higher reliability.

That's a ridiculous comparison. You're comparing a kernel which has had some of the best programmers in the world work on it to ... everything ever written in Java?

Mocking a class permits testing just that exact class in isolation. That has clear advantages for testability and hence for reliability. Is it the best tool? I don't know, but the interesting question for most users is how does it work for standard business programmers working under time pressure, not how does it work for Linus Torvalds when he's been working on the same program for 30 years.

Packaging Rust for Fedora

Posted Oct 31, 2022 0:53 UTC (Mon) by khim (subscriber, #9252) [Link] (9 responses)

> You're comparing a kernel which has had some of the best programmers in the world work on it to … everything ever written in Java?

No, just typical “enterprise app” whose development cost comparable sum to what development of kernel cost.

And you can not say that kernel is written by “some of the best programmers in the world” and then turn around and claim that they just don't understand the good design when they see it.

> Mocking a class permits testing just that exact class in isolation.

Nope, you don't need mocks for that. If you class permits the disconnect in production (e.g. if you permit choice of either mysql or postgresql) then you can change that part for testing. If there are no possibility of separating two components or classes in production then why the heck do you want to separate them in your tests? Mocks are not the way to test interfaces, they increase coupling instead of decreasing it!

> That has clear advantages for testability and hence for reliability.

Quite the contrary. Simple example: suppose I have a parser and I decided to improve it's performance by adding some buffering to it… it would pass all tests you can imagine without mocks… but mocks would make it fail (because mock wouldn't provide enough data to fill the buffer).

Now, I have to change mocks and would make them match new expectations from what must be provided for my parser — which means I'm writing new code without tests (there are no tests for mocks because if you start going that way when would you stop).

And it's easy to write mock in a way that it always fills the buffer requested and never returns less data then what was requested (unlike the real thing). Eventually you reach the state where your mocks model everything badly and incorrectly. And then your tests pass but code throws exceptions left and right if it can be used at all.

Yes, mocks allow you to test code in isolation, but that's a problem, not an advantage. It reduces reliability of the whole system, not increases it. Some even say that they only way to properly test something is to test “everything like in production”. I wouldn't go as far, but the larger piece of your system is covered by a single test then higher chance it gives to you that test verifies something important.

Mocks go in the opposite direction and thus are not needed nor desired for reliability. Try again.

> I don't know, but the interesting question for most users is how does it work for standard business programmers working under time pressure, not how does it work for Linus Torvalds when he's been working on the same program for 30 years.

Maybe, but from observations it doesn't work all that well for them either. Git (entirely new project) went from rought idea to usable product much faster then any Java-business project I know. And yes, I know that Linus Torvalds is brighter than “most standard business programmers”. That wasn't the big reason.

The big reason was that Linus knew what he wanted and he knew what tests he needs and what tests he doesn't need. “Standard business programmer” just does motions which were designed to achieve things he doesn't know about and then tries to fix issue which not need fixing while simultaneously missing things that do need fixing.

It's telling that you couldn't event explain what property mocks are trying (and failing) to achieve and which, indeed, is hard, almost impossible to test without mocks in Simula67-style OOP languge like Java.

Packaging Rust for Fedora

Posted Oct 31, 2022 2:30 UTC (Mon) by dvdeug (guest, #10998) [Link] (1 responses)

> No, just typical “enterprise app” whose development cost comparable sum to what development of kernel cost.

https://lwn.net/ml/linux-kernel/CAHk-=wj6y5fipM2A5kEuOO9q... lists over 100 contributors to Linux 6.1-rc1. Assuming that has lasted over the past 30 years, I don't know how many enterprise apps there are with 3000 man years in them.

> And you can not say that kernel is written by “some of the best programmers in the world” and then turn around and claim that they just don't understand the good design when they see it.

That's not what I said. I will say that the best anything in the world frequently don't understand how the average person in a field can best do something.

> Some even say that they only way to properly test something is to test “everything like in production”.

Which is a cause of a huge number of bugs. For one thing, the hardware your code will run on in a few years usually doesn't exist. For another, it's hard to predict what production will be like. At worst, that comes down to "it works on my system".

> The big reason was that Linus knew what he wanted

Yeah, I don't think a single programmer writing a source-control system to his own whims is very closely related to writing a large team writing code to external specifications.

Packaging Rust for Fedora

Posted Oct 31, 2022 7:49 UTC (Mon) by Cyberax (✭ supporter ✭, #52523) [Link]

> https://lwn.net/ml/linux-kernel/CAHk-=wj6y5fipM2A5kEuOO9q... lists over 100 contributors to Linux 6.1-rc1. Assuming that has lasted over the past 30 years, I don't know how many enterprise apps there are with 3000 man years in them.

Amazon has something like 50000 developers working on AWS. I believe Microsoft and Google have similar numbers. Even given that the average AWS developer is far from the level of kernel developers, the aggregate amount of code that they produce is staggering.

You really underestimate the size of modern large applications.

Packaging Rust for Fedora

Posted Oct 31, 2022 8:18 UTC (Mon) by Wol (subscriber, #4433) [Link] (5 responses)

> Maybe, but from observations it doesn't work all that well for them either. Git (entirely new project) went from rought idea to usable product much faster then any Java-business project I know. And yes, I know that Linus Torvalds is brighter than “most standard business programmers”. That wasn't the big reason.

> The big reason was that Linus knew what he wanted and he knew what tests he needs and what tests he doesn't need. “Standard business programmer” just does motions which were designed to achieve things he doesn't know about and then tries to fix issue which not need fixing while simultaneously missing things that do need fixing.

Which is why I bang on about how Pick projects are better than SQL. Pick makes programming accessible to the END USER. Which is why projects actually do what is required at the first attempt!

Okay, without proper programmer/analyst input right from the start, the result can easily be a horrendous ball of spaghetti, but when you have programmers and end users working TOGETHER, then the result is brilliant. Far too many projects, the end user tells the analyst what they want, the analyst specs the system, then maybe the designer designs it, before the programmer writes it. Chinese Whispers all the way. The programmer never sees an end user, half the people in the chain are clueless as to what the system is really wanted to do, and the result is a late, over budget, half-implemented ass of a solution.

Cheers,
Wol

Packaging Rust for Fedora

Posted Oct 31, 2022 12:04 UTC (Mon) by khim (subscriber, #9252) [Link] (4 responses)

> Which is why I bang on about how Pick projects are better than SQL.

SQL is awful abomination in theory, but there are many decent free implementation which work reasonably well in practice.

Pick is better in theory but there are no decent free implementations which makes it non-starter for many projects.

I would love to use Pick instead of SQLite for my [pretty] modest needs but SQLite is free and integrates very well with other tools which Pick…

Well, maybe someone would solve that problem. Hey, before Rust I was 100% sure the mistake that world made quarter century ago (when it picked OOP and GC as the main road which obviously leads us nowhere) would never be fixed.

Maybe something like that would, eventually, happen with databases, too?

Packaging Rust for Fedora

Posted Nov 1, 2022 12:47 UTC (Tue) by Wol (subscriber, #4433) [Link] (3 responses)

SQL is an awful abhomination in practice ...

I've just been involved in a migration from SQL/Relational to SQL/Relational. It's over-run its cost budget, it's over-run its time budget, it's been a bit of a disaster ... (Not in causing any real problem to the company, but just in the endless delays ...)

Part of this has been "where is this field defined?". We've got assorted measures like DPR (part of our efficiency metric), which is calculated in god-only-knows how many places, the definition has chnged over time, where the hell is the current definition and is it used consistently ...

Because Pick does NOT distinguish between tables and views, because Pick has virtual columns, because Pick is (or can be) object orientated, it's EASY to have just the one definition, in the one place, and THAT'S IT. As soon as you try defining virtual columns in Relational, they end up strewn over multiple tables, and managing it is a nightmare.

Then there's the simplicity of defining your FILE. You define your Real columns just like in Relational. Then because Pick defines by iterating through rows, you define your Virtual columns with a function like Excel vlookup. You don't have this horrendous 100-line (if you're lucky enough for it to be that small) abhomination of a SQL view. So your virtual field is defined as part of the FILE that is the object of interest, and if you need it anywhere else, you just create a virtual field that references the master definition and pulls it across.

Can't remember whether I said, but seeing as I'm going to be integrating ScarletDME with Google Sheets and BigQuery, it comes with an Excel connector, there's a whole bunch of JSON, web, whatever connections available if you want it ... if you've got time to play download it, reach out to me if you want, go onto the relevant google groups, and I'll do everything I can to help ...

Cheers,
Wol

Packaging Rust for Fedora

Posted Nov 1, 2022 15:41 UTC (Tue) by kleptog (subscriber, #1183) [Link] (2 responses)

IMHO if you're doing anything significant in SQL, an ORM with a generative query API is a must. Then you have a single source of truth for your database structures. The environment can validate the queries at compile time. Migrations can be autogenerated. And you can write your queries in a way that makes sense. If this results in 20KB queries being sent to the SQL server, that's Not My Problem.

Packaging Rust for Fedora

Posted Nov 1, 2022 15:58 UTC (Tue) by Wol (subscriber, #4433) [Link] (1 responses)

ORM?

(Oh, and 20kb queries aren't the problem. It's queries that are hand-written and huge. And by the way, the guys expected to write the queries are NOT database bods, they're end users who need the information. (And without whom, there's no point having a database!!!))

Oh - and if ORM means "Object Relational Model", then just ditch the relational and use Pick instead :-)

Cheers,
Wol

Packaging Rust for Fedora

Posted Nov 1, 2022 23:24 UTC (Tue) by ssokolow (guest, #94568) [Link]

They're probably lumping anything with a query builder API under "ORM", even though things like Python's SQLAlchemy make the Object-Relational Mapper layer an optional higher-level wrapper around the lower-level query builder system.

Packaging Rust for Fedora

Posted Dec 3, 2022 6:38 UTC (Sat) by ghane (guest, #1805) [Link]

> “Standard business programmer” just does motions which were designed to achieve things he doesn't know about and then tries to fix issue which not need fixing while simultaneously missing things that do need fixing.

This. Precisely this.

Developers keep opening issues that make no business impact, and keep trying to solve every issue with a combination of StackOverflow and copy/paste.

This week, I have been trying to explain to a team why they should remove an "UpdatedAt" database field from a table that is an immutable append-only log. "But every other table has a CreatedAt and UpdatedAt field!"

Meanwhile, users see "Oops an Error happened" popups. "OK" button.

Packaging Rust for Fedora

Posted Oct 31, 2022 13:55 UTC (Mon) by mathstuf (subscriber, #69389) [Link]

> Mocking a class permits testing just that exact class in isolation.

I think you mean "things using that class".

However, I have managed to get away with zero "class mocks" in my Rust code as well. The `#[test]` attribute allowing tests to be written right beside the code under test helps a lot as it also means that Rust's visibility rules allow the tests to reach "behind the curtain" to do things as necessary (for setup or validation). About the only thing I've mocked is remote services which…are easy to mock without mucking with the actual code since the codebase is abstracted over remote implementations already (GitLab or Github), so adding one that just uses in-memory storage and a tempdir for all of its bits is easy enough.

Packaging Rust for Fedora

Posted Oct 31, 2022 4:25 UTC (Mon) by ssmith32 (subscriber, #72404) [Link]

"And many people online ask if every class should have an interface; among other things, that makes the object mockable."

And the correct answer is always "no".

Because:
- It pointlessly doubles the number of files you have to deal with.
- It pointlessly increases how long it takes to navigate from a call site to an implementation when debugging.
- It doesn't "make an object mockable". Because you can mock objects just fine without them. Mockito, et. al.

This is from working at several different companies on largely Java codebases. New Java folks come in and having read some book by Crazy Uncle Bob or some such nonsense, and they learn quickly that it's not a good idea.

Interfaces should only be used when you *need* multiple implementations. And, no, your hand-rolled mock does not count. You should have used Mockito.


Copyright © 2025, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds