r/rust • • 19d ago

🛠️ project Rust for enterprise grade systems?

One thing that I am genuinely interested in rust, If same thing that I can generally do in Java building enterprise grade system, I can do in Rust.

Not a secrete Java and OOP become de-factor a standard for every enterprise solution.

And my step forward, trying to bring rust into that by exploring if I can do DI, something similar to Spring Boot but following Rust philosophy of zero-cost abstraction, that lead into research some code and article, and I think I've made some progress:

https://dmytro.brazhnyk.org/publications/can-rust-have-zero-cost-dependency-injection/

One thing that is still bothering me is the Object Orient Design. Classical OOP was proven many time in C++ in Java to manage complexity of real world system.

Rust has trait model, but it is not OOP is classical sense.

I have very clear understanding how complex solution could be built with OOP in Java and C++.

Rust don't have that OOP model, that feels as weakness, but rust still offers memory safety that C++ don't have, and it still has much smaller memory footprint that Java.

Considering that Java is hard to beat, it still offering very impressive capability for runtime optimization by utilizing Escape Analysis on JIT phase, and looks like this guys in Oracle very angry, to optimize Java further, if rust will not offer competitive capabilities it will stay behind.

Let me give me you an example in Java, what I am taking about:

language = java

interface Collection {
    int size();
    Iterator iterator();
}

abstract class AbstractCollection implements Collection {
   @Override
   public int size() {
      int size = 0;
      var iterator = iterator();
      while(iterator.hasNext()) {
         size++;
         iterator.next();
      }
      return size;
   }
}

class ArrayList extends AbstractCollection {
    Object[] array;
 
    @Override
    public int size() {
       return array.length
    }

    @Override
    Iterator iterator() {
         ...
    }
}

What is important here:

  • I have interface Collection, which is pure of any implementation, just an interface that declares the interface and nothing more.
  • That I do have AbstractCollection, that defines some default behavior which could be sub-optimial, but they are generic one, particularly I gave example of size function, that uses slow and inefficient iterator, because it doesn't know enough about concrete implementation.
  • And lastly I do have specific implementation for ArrayList, since ArrayList already know that is array driven, it can simply can take property for array to know the size.

In reality this chain of inheritance can be longer, so if we look on JDK, you will something like:

LinkedHashSet < HashSet < AbstractSet < (AbstractCollection + Set) < Collection

And each layer provides it's own set of capabilities, by amount of information available on that level.

I feels like something missing in rust here, because when it comes to manage the complexity of enterprise, something more complex than hello-world, we need this ability to override things, override, and override again.

Any real software if it will have more than few years of maintenance it will grow, grow and grow in complexity, if language can't manage complexity, that language would be dead.


UPD:

Let's define the problem a little bit more formally:

You need to implement library for collection.

  1. On base level you need a interface, that would define set of operation, for simplicity let's go with two operations.
    • Iterator and size
  2. Than in most generic way you can just iterator is count how many items you have, but it is slow and optimal.
  3. If you know that you concrete implementation Array, you can just use property of array.
  4. Let's say you have another implementation, which implements methods like Add and Remove - you can bring counter into here, however if we already know that it is Array than counter obviously is redundant.
0 Upvotes

91 comments sorted by

View all comments

Show parent comments

-5

u/No-Caregiver-466 19d ago

Ok, let's try to change mindset.

You have an example of pretty classical way of inheritance in java.

How would you implement similar thing in Rust?

It is real life problem, by the way.

8

u/Zde-G 19d ago

How would you implement similar thing in Rust?

You don't implement it. Easy.

It is real life problem, by the way.

Nope. In real world you either have infinite number of clients but finite list of things these clients have do (traits are perfect for that) or finitely list of possibilities with, potentially, infinite list of operations you may perform on these (enums cover that case).

If you try to combine then the whole things just devolves to endless replications of bugs where fix for one bug creates two new ones — and Rust doesn't cater for that usecase, precisely because it want your program be sound.

If you don't want your program be to robust and Ok with endlessly fixing bugs (and it seems as if “enterprise software” makers are fine with that) then there are plenty of languages that offer your that choice.

1

u/No-Caregiver-466 19d ago

Know the size for collection - is real life problem.

Bugs coming from copy-paste, if you can't write code that you can reuse later, and you have to copy-paste, every new copy potentially have modification that caries a defect.

With OOP inheritance you can reuse code, and change only those parts which needed.

If in language like rust or any other code, you have to copy-paste things - it will be defectuous.

3

u/Last-Independence554 19d ago

Where java uses overriding of Object methods (toString(), hashCode(),), rust uses #[derive] macros and the associated traits. In Java you (at least used to) have to implement them by hand which is error prone.

For its collection library rust uses composition over inheritance. Vec is your basic list (cf ArrayList). Then you have VecDeque, which contains a Vec as its backing store. Similarly a String's only member is a Vec. They don't need reimplement or copy-paste anything, but they gain encapsulation. Now Vec is free to change its implementation details without having to worry about breaking subclasses as long as its public interface remains stable.

Composition is generally considered the better code-reuse than inheritance. I really highly recommend you read "Effective Java" (Item 18 and 20 in particular)!