Should we adopt Dave's way of building applications as a series of components? (Dave's talk has now been added!)

Clean doesn’t automatically translate to well-organized, it’s well-organized that has a habit of looking clean.

For the longest time it was a best practice to keep your HTML, JavaScript, and CSS separate in the name of “separation of concerns” (markup vs behaviour vs appearance) but these days people sing the praises of Vue components which let you combine JavaScript, (pseudo-)markup and CSS because it allows them to keep things together that change together (CSS can be a bit tricky because you have to separate structural from cosmetic CSS).

Just my opinion™:

The end result is files of code that rarely go above 200 lines of code and that only have 1 public entry point.

While I agree that small file sizes are desirable, size isn’t an absolute measure. There are always exceptions to the “rule” - but all exceptions have to be justified. And there is such a thing as files that are too small - if they separate things that belong together (i.e. lack of cohesion). That being said, most of the time a large module is concealing multiple small modules struggling to get out. The point is: “it depends”; as unhelpful as that may be in the general case.

Making things easier to reason about is about partitioning your problem space into well defined concepts that build on one another.

Some of the smallest concepts can be represented by a single line of code - which I personally have no qualms sticking in a single named function - not for reuse but because the name is a better representation of the concept than that line of code. Software that Fits In My Head essentially states that code needs to fit on a single screen to be easy to reason about. That single screen can, via named functions, refer to thousands of lines of code off-screen as long as those functions implement clearly (and coherently) defined concepts in the problem domain and still be easy to reason about. Now when a single function doesn’t fit on a single screen questions need to be asked. But (module) file size isn’t necessarily an indicator as to whether it is easy to reason about.

In my personal judgement some things that jump out at me:

  • The code organization is dominated with concerns about resources, while at the same time the role that product plays in the problem domain is completely obscured. This system clearly serves resources but what problem do these resources serve? This is similar to a Rails application always looking like a Rails application, regardless of what the Rails application was actually created to do.
  • Controller, Handler, View deal with the representation. In my mind Logic, Model, and Repo are not part of the network interface implementation so they don’t belong here and there is likely functionality that needs to be shared across New, Modify, Discontinue. Also in REST I would see the controller as a manifestation of the Uniform Interface ({POST,New},{PUT,Modify},{DELETE,Discontinue}) so I would expect it on the Product level, no lower.
  • REpresentational State Transfer is an architectural style but as such only describes the protocol for how applications can interact over a network that observes the constraints as established by the HTTP protocol. But that doesn’t imply that the “resource organization structure” necessarily has to continue into the deepest bowels of your system. Doing so may superficially make your job easier right now when you are building the application for the first time with a bare minimum of capabilities - but the rigidity of this approach will likely make changes more difficult in the future. The internal system architecture should be optimized for what the system is supposed to do. The resource-oriented interface is then designed and built on top of that, “inventing” whatever additional resources are necessary to enable the necessary business transactions.

Software that is developed with re-usability,

This is an idea who’s time has passed.

Intentionally provocative but the point being is that lots of complexity has been committed in the name of reusability that has never delivered on the promise. Often you need more than two different places that want to use something before you can determine what is truly generic/reusable rather than trying to predict what (and how it) should be reusable.

The Rocky Mountain Ruby 2016 - Kill “Microservices” before its too late by Chad Fowler topic features lots of content that explores the notion that replaceability rather than reusability can be the more important design concept for successful systems.

12 Likes