Show HN: I Wrote a Book on Java

334 points by goostavos 8 hours ago

https://www.manning.com/books/data-oriented-programming-in-j...

This book is a distillation of everything I’ve learned about what effective development looks like in Java (so far!). It's about how to organize programs around data "as plain data" and the surprisingly benefits that emerge when we do. Programs that are built around the data they manage tend to be simpler, smaller, and significantly easier understand.

Java has changed radically over the last several years. It has picked up all kinds of new language features which support data oriented programming (records, pattern matching, `with` expressions, sum and product types). However, this is not a book about tools. No amount of studying a screw-driver will teach you how to build a house. This book focuses on house building. We'll pick out a plot of land, lay a foundation, and build upon it house that can weather any storm.

DoP is based around a very simple idea, and one people have been rediscovering since the dawn of computing, "representation is the essence of programming." When we do a really good job of capturing the data in our domain, the rest of the system tends to fall into place in a way which can feel like it’s writing itself.

That's my elevator pitch! The book is currently in early access. I hope you check it out. I'd love to hear your feedback.

You can get 50% off (thru October 9th) with code `mlkiehl` https://www.manning.com/books/data-oriented-programming-in-j...

raju 8 hours ago

Let me start by saying (as someone who has written a few technical books of his own)—Congratulations!

I am sure you (assuming this is your first book) are learning that this is a labor of love, and I wish you the very best in this endeavor. You should be proud!

I was exposed to "data oriented programming" thanks to Clojure—wherein maps/sets are the constructs used to pass data (as plain data) around, with simple functions that work with the data, as opposed to the traditional OO (hello ORM) that mangles data to fit some weird hierarchy.

Java's recent innovations certainly make this a lot easier, and I am glad someone is looking at propagating a much needed message.

I will take a look at the book, but I wish you the very best.

  • mrbonner 8 hours ago

    I am also very interested in how this work in practice. With OOP at least you know the shape of your data structure as opposed to the hash map as a mere container type.

    • geophile 7 hours ago

      I am an OOP programmer going back to the late 80s (including the cfront days of C++), and a serious user of Python since 2007.

      In Python, I sometimes try data-oriented programming, using lists and dicts to structure data. And I find that it does not work well. Once I get two or more levels of nesting, I find it far too easy to get confused about which level I'm on, which is not helped by Python's lack of strong typing. In these situations, I often introduce objects that wrap the map or dict, and have methods that make sense for that level. In other words, the objects can be viewed as providing clear documentation for the whole nested structure, and how it can be navigated.

      • goostavos 7 hours ago

        >Once I get two or more levels of nesting, I find it far too easy to get confused about which level I'm on

        Author here, I agree with you. I have the working memory of a small pigeon.

        The flavor of data orientation we cover in the book leverages strongly typed representations of data (as opposed to using hash maps everywhere). So you'll always know what's shape it's in (and the compiler enforces it!). We spend a lot of time exploring the role that the type system can play in our programming and how we represent data.

        • joshlemer 7 hours ago

          Given the strongly typed flavour of data oriented programming, I wonder if you have any thoughts on the "proliferation of types" problem. How to avoid, especially in a nominally typed language like Java, an explosion of aggregate types for every context where there may be a slight change in what fields are present, what their types are, and which ones are optional. Basically, Rich Hickey's Maybe Not talk.

              record Make(makeId, name)
              record Model(modelId, name)
              
              record Car(make, model, year)
              record Car(makeId, modelId, year)
              record Car(make, model)
              record Car(makeId, modelId)
              record Car(make, year)
              record Car(makeId, year)
              record Car(make, model, year, colour)
              record Car(makeId, modelId, year, colour)
              record Car(year, colour)
              
              ....
          • PaulHoule 3 hours ago

            Hickey is great at trash-talking other languages. In the case of Car you might build a set of builders where you write

               Car.builder().make(“Buick”).model(“LeSabre”).build()
            
            Or in a sane world code generate a bunch of constructors.

            In the field of ontology (say OWL and RDF) there is a very different viewpoint about ‘Classes’ in the objects gain classes as they gain attributes. :Taylor_Swift is a :Person because she has a :birthDate, :birthPlace and such but was not initially a :Musician until she :playsInstrument, :recordedTrack, :performedConcert and such. Most languages have object systems like Java or C++ where a Person can’t start out as not a Musician but become one later like the way they can in real life.

            Notably in a system like the the terrible asymmetry of where does an attribute really belong is resolved, as in real life you don’t have to say it is primary that Taylor Swift recorded the Album Fearless or that Fearless was recorded by Taylor Swift.

            It’s a really fascinating question in my mind how you create a ‘meta object facility’ that puts a more powerful object system on your fingers in a language like Java or Python, for instance you can have something like

               taylorSwift.as(Musician.class)
            
            which returns something that implements the Musician.class interface if

               taylorSwift.isA(Musician.class)
            
            where

               TaylorSwift instanceof MetaObject.class
          • goostavos 6 hours ago

            I have a long convoluted answer to this.

            I love that talk (and most of Rich's stuff). I consider myself a Clojure fanboy that got converted to the dark side of strong static typing.

            I think, to some degree, he actually answers that question as part of his talk (in between beating up nominal types). Optionality often pops up in place of understanding (or representing) that data has a context. If you model your program so that it has "15 maybe sheep," then... you'll have 15 "maybe sheep" you've got to deal with.

            The possible combinations of all data types that could be made is very different from the subset that actually express themselves in our programs. Meaning, the actual "explosion" is fairly constrained in practice because (most) businesses can't function under combinatorial pressures. There's some stuff that matters, and some stuff that doesn't. We only have to apply typing rigor to the stuff that matters.

            Where I do find type explosions tedious and annoying is not in expressing every possible combination, but in trying to express the slow accretion of information. (I think he talks about this in one of his talks, too). Invoice, then InvoiceWithCustomer, then InvoiceWithCustomerAndId, etc... the world that microservices have doomed us to representing.

            I don't know a good way to model that without intersection types or something like Rows in purescript. In Java, it's a pain point for sure.

            • jakjak123 6 hours ago

              Hopefully your domain is sane enough that you can read nearly all the data you are going to use up front, then pass it on to your pure functions. Speaking from a Java perspective.

            • 1propionyl 6 hours ago

              My sense is that what's needed is a generalization of the kinds of features offered by TypeScript for mapping types to new types (e.g. Partial<T>) "arithmetically".

              For example I often really directly want to express is "T but minus/plus this field" with the transformations that attach or detach fields automated.

              In an ideal world I would like to define what a "base" domain object is shaped like, and then express the differences from it I care about (optionalizing, adding, removing, etc).

              For example, I might have a Widget that must always have an ID but when I am creating a new Widget I could just write "Widget - {.id}" rather than have to define an entire WidgetCreateDTO or some such.

              • glenjamin 5 hours ago

                Do you mean in TypeScript or in another language?

                In TS the `Omit<T, K>` type can be used to remove stuff, and intersection can be used to add stuff

              • piva00 6 hours ago

                > For example, I might have a Widget that must always have an ID but when I am creating a new Widget I could just write "Widget - {.id}" rather than have to define an entire WidgetCreateDTO or some such.

                In this case you're preferring terseness vs a true representation of the meaning of the type. Assuming that a Widget needs an ID, having another type to express a Widget creation data makes sense, it's more verbose but it does represent the actual functioning better, you pass data that will be used to create a valid Widget in its own type (your WidgetCreationDTO), getting a Widget as a result of the action.

                • 1propionyl 3 hours ago

                  > Assuming that a Widget needs an ID, having another type to express a Widget creation data makes sense, it's more verbose but it does represent the actual functioning better

                  I agree with this logically. The problem is that the proliferation of such types for various use cases is extremely detrimental to the development process (many more places need to be updated) and it's all too easy for a change to be improperly propagated.

                  What you're saying is correct and appropriate I think for mature codebases with "settled" domains and projects with mature testing and QA processes that are well into maintenance over exploration/iteration. But on the way there, the overhead induced by a single domain object whose exact definition is unstable potentially proliferating a dozen types is developmentally/procedurally toxic.

                  To put a finer point on it: be fully explicit when rate of change is expected to be slow, but when rate of change is expected to be high favor making changes easy.

          • kentosi 2 hours ago

            I haven't yet had the luxury to experiment with the latest version of Java, but this is one of the reasons why I wish Java introduced named parameters the say way kotlin and scala do.

            Eg:

              data class Make(makeId: String, name: String)
              data class Model(modelId: String, name: String)
            
              data class Car(make: Make, model: Model, year: String, ...)
            
            Now you can go ahead and order the params whichever way you wish so long as you're explicitly naming them:

              val v1 = Car(make = myMake1, model = myModel1, year = "2023", ...)
              val v1 = Car(model = myModel1, make = myMake1, year = "2023", ...)
          • cbsmith 2 hours ago

            That one is pretty simple. You have a Car object with four fields. The types of the fields are, respectively Optional<Make>, Optional<Model>, Optional<Year>, and Optional<Colour>.

            Hickey makes it sound worse than it is.

          • geophile 6 hours ago

            This discussion sounds like there is confusion about the Car abstraction.

            Make and model vs. makeId and modelId: Pick one. Are Make and Model referenced by Cars or not? There seems a slight risk of the Banana/Monkey/Jungle problem here, so maybe stick with ids, and then rely on functions that lookup makes and models given ids. I think it's workable either way.

            As for all the optional stuff (color, year, ...): What exactly is the problem? If Cars don't always have all of these properties then it would be foolish of Car users to just do myCar.colour, for example. Test for presence of an optional property, or use something like Optional<T> (which amounts to a language supported testing for presence). Doesn't any solution work out pretty much the same? When I have had this problem, I have not done a proliferation of types (even in an inheritance hierarchy) -- that seems overly complicated and brittle.

          • nicoty 6 hours ago

            I'm not familiar with Java. Does it have no notion of structural types at all? If it does, maybe you could wrap those fields in `Car` with `Maybe`/`Option` (I’m not sure what the equivalent is in Java) so you get something like `Car(Maybe Make, Maybe Model, Maybe Year, Maybe Colour)`?

            • spullara 6 hours ago

              yes and it is called Optional (rather than Maybe)

      • js2 6 hours ago

        > Python's lack of strong typing

        I see people conflate strong/weak and static/dynamic quite often. Python is strong[1]/dynamic, with optional static typing through annotations and a type checker (mypy, pyright, etc).

        Perhaps the easiest way to add static types to data is with pydantic. Here's an example of using pydantic to type-check data provided via an external yaml configuration file:

        https://news.ycombinator.com/item?id=41508243

        [1] strong/weak are not strictly defined, as compared to dynamic/static, but Python is absolutely on the strong end of the scale. You'll get a runtime TypeError if you try to add a number to a string, for example, compared to say JavaScript which will happily provide a typically meaningless "wat?"-style result.

        • jstimpfle 4 hours ago

          In some significant ways, it's not strong at all. It's stronger than Javascript but it's difficult not to be. Python is a duck typing language for the most part.

          • js2 3 hours ago

            Duck typing is an aspect of it being dynamically typed, not whether it is strong/weak. But strong/weak is not formally defined, so if duck typing disqualifies it for you, so be it.

            https://langdev.stackexchange.com/questions/3741/how-are-str...

            • cbsmith 2 hours ago

              I always think of Python as having "fairly strong" typing, because you can override the type of objects by just assigning to __class__.

      • cbsmith 2 hours ago

        Living this dream in Python right now (inherited a code base that used nasty nesting of lists & dicts). You don't strictly need to do OOP to solve the problem, but it really does help to have a data model. Using dataclasses to map out the data structures makes the code so much more readible, and the support for type hints in Python is good enough that you can even debug problems with the type system.

      • mejutoco 7 hours ago

        I recommend you use pydantic for type annotations. Alternatively, dataclasses. Then you pair it with typeguards @typechecked annotation and the types will be checked at runtime for each method/function. You can use mypy to check it at "compile time".

        Having clear data types without oop is possible, even in python.

      • sodapopcan 7 hours ago

        Python's not really built for that AFAIK, though. In languages built for it, you can type your dicts/hashes/maps/whatever and its easier to see what they are/know where the functions that operate on them live. I'm most familiar with Elixir which has structs which are simply specialized map (analogous to dict in Python) where their "type" is the name of the module they belong to. There can only be one struct per module, In this sense is easy to know exactly where its functions live and is almost like a class with the very key difference that modules are not stateful.

        • cbsmith 2 hours ago

          > In languages built for it, you can type your dicts/hashes/maps/whatever and its easier to see what they are/know where the functions that operate on them live.

          I think I must be misunderstanding what you mean by that, because I can very much do that in Python.

      • FpUser 7 hours ago

        >"In these situations, I often introduce objects that wrap the map or dict, and have methods that make sense for that level."

        I've been doing the same thing since the end of the 80s as well starting with Turbo/Borland Pascal, C++, and later any other language that supports OOP.

    • kccqzy 7 hours ago

      Clojure has spec. That allows you to know a specification of what the data structure contains.

    • akavi 7 hours ago

      You can get strongly typed "shaped" data without objects[0], even in Java: Records[1].

      ~Unfortunately, I believe they're mutable (and cannot be made immutable).~ Edit: I was wrong, they're immutable.

      [0]: I'm using "object" to mean "data bound to methods", since the concept of aggregate data in general long pre-date OOP (eg, C's structs)

      [1]: https://docs.oracle.com/en/java/javase/17/language/records.h...

      • taftster 7 hours ago

        Java Records are immutable (by the most common definition). They don't have any means to update the record (via setters, etc.) after construction. That doesn't mean, for example, you can't store a reference to a mutable type (for example, a List or Map) in your record.

        The frustration I have with Records is there is no good way to prevent direct construction of them. That is, the constructor is public, which prevents an easy way of enforcing an invariant during construction.

        For example, let's say that you have a record with a Date type. There's no good way to prevent a user from creating the record with an invalid date, one that is out of a needed date range. Or maybe enforcing a field cannot be null or some combination of fields must meet requirements as a group.

        The benefit I get from the classic Builder pattern is defeated with Records. I can't enforce checking of my fields before the construction of the record object itself. Presumably I would need to verify the object after construction, which is unfortunate.

        • vips7L 7 hours ago

          You can enforce some invariants during construction:

              record Point(int x, int y) {
                  Point {
                      if (x < 0) throw new IllegalArgumentException()
                  }
              }
          
          or if you want to assert something is not null:

              record Person(String name) {
                  Person {
                      requireNonNull(name);
                  }
              }
        • tpmoney 4 hours ago

          As mentioned by the other commenters, you should be able to run any validations or transformations on the data that you want in the canonical constructor, including re-assigning values (for example we've done defaults with `foo != null ? foo : new DefaultFoo()`). The only thing I think you can't do with a record is make the canonical constructor private and force users of your type to call factory methods that can return null instead of throwing an exception. You can provide those factory methods, but anyone can still call the constructor, so you have to do your hard checks in the constructor. On the other hand, no matter how many alternate constructors or factory methods you make, you're also guaranteed that every one of them eventually has to call the canonical constructor, so you don't need to spread your validation around either.

        • snmx999 6 hours ago

          You can create dedicated, already verified objects to pass on to your record. E.g. AllowedDate (extends Date).

        • akavi 7 hours ago

          Can you make the Record class private to a module, and only export a static function that constructs them?

          (I know very little about Java)

          • kaba0 7 hours ago

            To a degree, yes, that’s possible. But leaking a private type over module boundaries is bad form, so a better (though possibly over engineered solution) would be to have a separate public interface, implemented by the private record type, and the static function would have that interface as return type.

            • enugu 2 hours ago

              Why is it bad form to expose a record type only via custom functions and not its field accessors? Isn't this just like exposing a more usual object with its public functions and private functions remain inaccessible?

      • bedatadriven 7 hours ago

        A record's fields are final, so records are immutable (though they can include immutable pointers to mutable objects)

  • goostavos 8 hours ago

    Thanks for the kind words :)

    >learning that this is a labor of love

    I underestimated both the amount of labor and the amount of love that would be involved. There were more than a few "throw everything out and start over" events along the way to this milestone.

    Clojure definitely had a huge impact on how I think about software. Similarly, Haskell and Idris have rearranged my brain. However, I still let Java be Java. The humble object is really tough to beat for managing many kinds of runtime concerns. The book advocates for strongly typed data and leveraging the type system as a tool for thinking.

    >Java's recent innovations certainly make this a lot easier

    Yeah, it's an exciting time! Java has evolved so much. Algebraic types, pattern matching, `with` expressions -- all kinds of goodies for dealing with data.

topspin 7 hours ago

How have you dealt with the current situation in Java where several new and important language features are still "preview" and are subject to being withdrawn? The possibility that these features might ultimately disappear is not theoretical: String Templates has been removed[1] from 23 as what would have been the "third preview," for example.

The (likely debatable) list of features in 23 that a.) remain preview/incubator and b.) appear relevant to a work on data oriented Java programming are:

    Primitive Types in Patterns, instanceof, and switch (Preview) – JEP 455
    Implicitly Declared Classes and Instance Main Methods (Third Preview) – JEP 477
    Flexible Constructor Bodies (Second Preview) – JEP 482
    Vector API (Eighth Incubator) - JEP 469
    Scoped Values (Third Preview) – JEP 481
[1] https://mail.openjdk.org/pipermail/amber-spec-experts/2024-A... "So, to be clear: there will be no string template feature, even with --enable-preview, in JDK 23." - Gavin Bierman
  • goostavos 7 hours ago

    I've thought a lot about this quite a bit. In my day to day life, which is a cog in the machine at $Megacorp, I regularly work on embarrassingly old versions of Java (hello JDK 8!). So, not having the latest and greatest language features is a topic close to my heart. As such, the book takes a very tool agnostic approach. If we cover something that's only available advanced JDKs, we also cover what to do if you don't have it.

    Data oriented programming is about building around the data in your domain. The latest tools are nice, but they're just tools.

    • topspin 7 hours ago

      I appreciate your conundrum. While it has been good to see Java language designers attempt to advance the language, they've been extremely conservative and non-committal. This is a problem because tooling is costly to develop and tool developers are forever facing the problem of whether to invest the work needed to integrate these language features when they take years to be realized, and may yet vanish. Likewise for authors, such as yourself.

  • whartung 7 hours ago

    I can't say I'm completely on top of the Java world, but I think the String Templates are one of the very few preview features that have been actually withdrawn and removed, right? Are there others?

    I know some drift a bit on their implementations over time, but have not be wholesale yanked out.

    Obviously the solution to this is to not rely on these preview functions for production code. The way to do that is to run production in an LTS version of Java. I don't think that's an extreme point of view, frankly.

    The new stuff is interesting and cool, and in time, it ends up in the LTS version.

    Having lived through Java 5, 6, and 8, these are halcyon times for Java. It's moving VERY fast, and has been for some time.

    Are there preview capabilities in the LTS versions? Yes, there are. But they're not under the LTS tent. Don't use them. The demarcation between the development releases and the LTS releases are a smart program to get features out into the world, and set some real lines in the sand for advancement. It helps keep preview items from staying in preview mode for an indeterminate amount of time.

    And the two year LTS release cycle for a notoriously conservative eco-system is ample.

    • topspin 6 hours ago

      > Are there others?

      String Literals (JEP 326) made it to preview and got pulled.

      > I don't think that's an extreme point of view, frankly.

      Can't see where I suggested otherwise. I just wondered how the author was handling all the "in-flight" (An OpenJDK term there, not mine) features that Java currently has outstanding.

      > It's moving VERY fast, and has been for some time.

      They've been fast at creating new preview features. Actually landing finalized features though? In my view they're taking too long. When I compare Java and Python in this respect -- and I do as a working programmer in both on a frequent basis -- Java is still slow.

      • perrylaj 4 hours ago

        > When I compare Java and Python in this respect -- and I do as a working programmer in both on a frequent basis -- Java is still slow.

        I feel this as well, but I also think it's desirable. Java is slower to add features because the bar is quite a bit higher (especially with regard to backwards-compatibility).

        I'd much rather have long previews and occasional removal of previews than have a language that becomes bloated and kneecapped by past rushed decisions.

        There's Kotlin, Scala, Groovy, etc, if you want to run on the JVM with languages that offer more features (and footguns). I find the balance OK, personally.

        I'd much rather them pull the `STR.` templates than push it forward knowing its not ergonomic in practice.

mands 8 hours ago

Technical Editor: Brian Goetz - you have my attention...

  • WoodenChair 7 hours ago

    Manning let me conduct an interview with Brian a few years ago for my book with them. Here is the transcript: https://freecontent.manning.com/interview-with-brian-goetz/

    He was very generous with his time and there are some good insights there for aspiring developers, as well as some info about the evolution of Java which may be relevant to the more data-oriented features that have been added in recent times.

  • goostavos 8 hours ago

    It has been awesome working with him.

    There are few things as intimidating as having the Java language architect review your book on Java (haha). It's a much, much better book thanks to his involvement.

  • flakiness 8 hours ago

    For people who're not aware: "Brian Goetz is a Java Language Architect at Oracle." (from the linked page.)

  • matsemann 6 hours ago

    While I'm normally not a fan of appeal to authority, knowing this is what moves this from "will try to remember to check this out when I wake tomorrow" (it's 23:04 here) to "will definitely check out tomorrow".

    Also it being from Manning helps. It's difficult to find good books today, so easy to self publish or get reeled in by some paper mill that banks on people wanting to have a book on their resume. So have to have something to filter out signal in the noise.

TeaVMFan 7 hours ago

Congratulations! In case people are looking for other modern Java books, here's one I'm working for building modern web apps in Java:

https://frequal.com/Flavour/book.html

It describes how to make single-page apps in Java, using the Flavour framework. No plugins, no extensions, and 99.9% pure Java. Plenty of sample code and links to relevant podcast episodes and demos.

  • mdaniel 7 hours ago

    Ok, I'll bite: why Subversion in 2024? https://sourceforge.net/p/flavour/trunk/HEAD/tree/

    > TeaVMFan

    Ah, that explains a lot of the questions I had about "modern webapps in Java." Relevant: https://news.ycombinator.com/item?id=25978053 (TeaVM: Build Fast, Modern Web Apps in Java; Jan 2021)

    Although I would, sincerely, enjoy hearing what KotlinJS doesn't do that made you want to roll your own framework?

    • TeaVMFan 3 hours ago

      Flavour supports multiple JVM languages. Plus it is a batteries-included framework, no need to look to extensions to get routing, templates, EL, JAX-RS support, and more.

xtreme 2 hours ago

As someone who loves Typescript, the first chapter of your book deeply resonated with me. Good data representations and data types that encode meaning can eliminate entire classes of bugs by making invalid states unrepresentable, and I wish more languages emphasized and supported these principles.

necovek 6 hours ago

First up, congrats on getting over the hump — I struggle to complete a blog post, so I very much appreciate the effort it takes to do this!

A confusing sentence I noticed in the first chapter:

> ...then the only thing cost was some time, if they do it wrong, the cost is usually a bug.

I am guessing you mean "only cost was some time" (without the "thing")?

As for the topic, my hypothesis is slightly different — adopting functional approach to programming — even in imperative languages — leads you to the best patterns (or as you put it, "makes it inevitable") when combined with "evolutionary" architecture, and DoP is certainly one of them.

However, for a majority of software, in my experience, data "attributes" are really "leaf nodes", only to be consumed for display, and types do not really matter much there (eg. I don't mind `firstName` being a simple string). What we want to get right is types we do operations on, and most critically, relations between different data models. Accepting "evolutionary" principles in architecture also means that you welcome change and build for it, so getting any definition of data right from start is not an imperative.

But the topic certainly seems intriguing, so I look forward to learning more from your book and seeing how you apply it in a more imperative/OO way and what language features you found critical to success there.

Congrats again and good luck!

  • necovek 6 hours ago

    Another typo:

    > ...no bad states to defend again.

    Defend "against", I guess?

    • goostavos 5 hours ago

      Oof -- embarrassing! At least I know what I'll be thinking about as I try to fall asleep tonight.

      Thanks for pointing out the typos and wonky wording! Will fix!

jhck 8 hours ago

Congrats on launching the early access! I'm familiar with data-oriented programming from Clojure and F#, and I'm interested in seeing how you approach it in Java, so I just picked up a copy (ebook). Wish you all the best on completing the book!

  • lloydatkinson 7 hours ago

    Do you have some F# examples of data orientated programming>? It seems to mean a lot of different things to different people.

    • goostavos 7 hours ago

      I can highly recommend excellent Domain Modeling Made Functional by Scott Wlaschin for an F# book that touches on a lot of the ideas which back data-oriented programming (namely, representing your domain as strongly typed data).

jroseattle 6 hours ago

Congrats on writing and completing a book! I was involved in a few myself long ago, when I had the time available to contribute to those endeavors. In a world that often measures "the juice being worth the squeeze", I'm not sure authoring technical manuals would ever meet the criteria.

One of my personal photos I keep around was taken long ago in what was the biggest bricks/mortar bookseller. I was looking at the selection of books on Java available at the time. O'Reilly was the dominant publisher, and thus had several offerings on the wall. Most of the books were at least 2 inches thick. (If you were ever involved with writing a technical book in the early 2000s, you'll understand the publisher metrics at the time were based on the width of the spine on the shelf.)

Among the many Java manuals of significant girth was a small, THIN book with the title "Java -- the Good Parts". :-{}

greyskull 8 hours ago

Congratulations!

I see that the book is incomplete. I didn't know that early access for books was a thing, very neat. It might be pertinent to note in your post that it's still being written, with an estimated release window of Spring 2025.

I'm very much a "consume it when it's ready" person, so I'll keep this on my watch list.

  • speerer 8 hours ago

    I wonder whether it's the editing which is still in progress, or also the writing? The publication date seems very close if it's still being written.

    (edit-clarity)

    • goostavos 6 hours ago

      Writing is still in progress :)

      No firm date for the final publication yet.

neeleshs 3 hours ago

Congratulations! I bought it and looking forward to the completed book.

The first chapter is pretty nice. Record types, switch statements and other new features will hopefully push Java programmers to think in terms of types more often.

blackqueeriroh 7 hours ago

Purchased! I know very little about programming still, but Java is a language I have dealt with and will likely continue to have to deal with for the rest of my career, so here we go!

burningChrome 8 hours ago

Congrats on your accomplishments!

I had two friends who both wrote separate books on JS. One early book on Angular and the other was about jQuery. Both had a hard time with the critical reviews they received on Amazon and it really dissuaded them from doing any more technical writing.

I love your approach and hope you keep writing and don't let the trolls get to you! Our industry needs more people who have this "soup to nuts" approach and take into account how nearly every language has changed dramatically over time.

Again, congrats and keep writing.

dzonga 6 hours ago

congrats. Data Oriented Programming is cool, but you can easily get lost in the complexity of certain things.

there's another related book from one person active in the Clojure ecosystem. Though the book examples are in JS.

also, thank you for taking the step forward on doing your own small part in changing the 'AbstractFactory' thinking that's pervasive in the Java world.

elric 6 hours ago

Does it include any content related to algebraic data types?

  • goostavos 6 hours ago

    It does! Chapter 4 specifically tackles modeling with sum and product types. They're used all throughout the book after that.

    • elric 6 hours ago

      Nice, thanks! The website suggests that the book will be published next spring. I'll be sure to preorder the print version.

smusamashah 7 hours ago

The link is returning 404 for me.

globular-toast 7 hours ago

How does DoP compare to Domain Driven Design (DDD)?

  • wredue 6 hours ago

    DoP is the brain dead assertion that making your data runtime immutable will make your programs better.

    It doesn’t. But the developers pushing it idiotic shit are extremely loud.

    • brookritz 5 hours ago

      These developers are immutable.

      • wredue 4 hours ago

        Nah. It is actually quite the opposite.

        What really happened is that I was full in on Scala and runtime immutability because I read the plethora of medium articles pushing this stuff and I believed it.

        Then I decided to use the stuff for myself and not a single claim that the runtime immutable crowd made panned out, and in fact, in many cases I found myself hard constrained in ways that fucking sucked (threading being a major one).

        Then when I took a more practical approach of filing runtime immutability under “tools” rather than “rules”, I stopping having major issues with data, stopped running in to bullshit productivity walls, and stopped running in to minor refactors automatically being major ones, and overall feature implementation became easier and faster.

        The only difference between me and the people pushing these things is that I actually decided to ask myself if the supposed benefits were actually panning out, and they didn’t.

        Over a few years I became tired of having the exact same stupid bullshit claims without evidence relentlessly pushed by zealots and just gave up with positive engagement with them. It doesn’t matter how much you ask for these people to provide the metrics that back up their claims, they never will. They will give bullshit anecdotes. They will write intentionally bad code in other paradigms. They will lie and lie and lie and lie some more.

        All that is to say that I am fully open to DoP being proven. They just have not done so.

    • elric 6 hours ago

      It would be nice if you could elaborate on why you think it's idiotic. What's "better" for one scenario could be worse for another. There are tradeoffs to be made.

      In my experience immutable data simplifies a lot of things and avoids a lot of common problems related to concurrency. Implementing efficient copy-on-write isn't too hard when everything is immutable.

      • wredue 5 hours ago

        You’re making your programs orders of magnitude slower to the back of claims that have absolutely zero metric demonstration.

        >simplifies a lot of things

        Runtime immutability simplifies nothing.

        >avoids common problems related to concurrency

        While simultaneously creating new problems. Like fine, you cannot make an edit on an object out from under the rug of another thread… except that in most cases, you have now just made that old object into invalid state that is lingering around your program like a death trap and to get around this, you are forced in to some pretty terrible synchronization bullshit that just locking objects doesn’t suffer from.

        >Implementing CoW is not too difficult

        The single greatest predictor of defects for every single language ever is “lines of code”. Implementing CoW sounds straight forward, but actually, incorrect CoW is a common source of bugs and you are just hand waving that away.

gwervc 8 hours ago

[flagged]

  • goostavos 8 hours ago

    This is the hardest I've ever been judged for a typo! haha.

das_keyboard 6 hours ago

As someone coming from gaming, somehow early-access for books seems weird