You can become a developer that knows his framework(s) very well. Your growth is in learning more frameworks and learn them better. You will have plenty to learn! And I don’t say this is necessarily bad. However…
To do this, you will need knowledge of a more fundamental nature. There is a world of things to learn! This kind of knowledge is more enduring, more versatile, more powerful.
Frameworks? Risk Functionality Performance Obsolescence Incompatibilities Developer Experience App startup time Test running time The bad The good Learning Standardisation Bad habits DB-Centric Quick project startup Extra work Upgrades Searching on Stackoverflow for answers Addiction Anything is good or bad in a particular context, for a particular set of goals.
I prepared a small demo of an API that plays the game of hangman. I wrote three versions of it; the first uses Spring and JPA. The second replaces JPA with plain JDBC calls. The third one removes Spring and uses the Servlet API.
HttpServletRequest HttpServletResponse A Java web application is (not exactly, but similar to) a function that transforms an HttpServletRequest into an HttpServletResponse.
HttpServletRequest HttpServletResponse WebRequest WebResponse However, those servlet API objects have 50+ methods and are very low level and hard to use. One key thing to make #frameworkless work well is to write simple code. Therefore, it’s good to transform the servlet API objects into something simpler and easier to use. These are custom made for each project, similar but never exactly the same thing.
HttpServletRequest HttpServletResponse WebRequest WebResponse GameResponse x HttpStatus GuessRequest And this is still not enough; for any particular request, we probably want to transform the WebRequest into a specific request object that contains exactly what we need.
The “Main Partition” The main and the servlet together are what Uncle Bob calls the “main partition”, that is, the place where objects are constructed. The main (of course) is executed once per process, while the servlet service method is executed once per request. It is a sort of “main” for the request.
The Router The router’s job is to decide what is the user trying to do, and dispatch to an appropriate service call. The code of the router is made much simpler by having some logic in the WebRequest and WebResponse.
The Router, part IIFor a simple service, a chain of IFs is simple and effective. If the service grows, it will probably evolve towards a table lookup. Again, this object should be developed afresh for every project/service. There’s no need to create a reusable “custom framework” here.
The Application Service The application service job is (a) to invoke business logic on domain objects, and (b) to deal with non-functional effects such as persistence.
The Game Repository The GuessRequest contains data that are not used by the business logic, but are relevant for audit/security/debug purposes. This information is saved in a way that does not pollute the business logic (compare the GuessRequest, shown later, with the Guess domain object) The QueryRunner is from Apache Dblib. It’s possible to write your own; it’s no more than 10 lines of code.
The Game Repository, part II Reconstructing a Game involves replaying all the “guesses” of the player. This not exactly event sourcing, but it’s similar. I find that saving all the “events” involving an aggregate, with as little processing as possible at write time, makes persistence simpler, even when you don’t go full event- sourcing. Perhaps this way can be even better than full event-sourcing :-)
The Web Request The API of the WebRequest is at the same time simpler and higher level than the servlet API. The getOptionalParameter() and getMandatoryParameter() methods simplify the router and the service.
Spring/JPA Spring/— —/— Server startup time ~6s ~3s 0.4s Time to run all tests 10s 5.5s 3.5s Time to run slowest test 7s 4-5s 1s # of tests 25 24 48 SLOC prod 360 424 643 SLOC test 358 357 745 jar size 30MB 17MB 6.3MB Judge for yourself.
Frameworks? Risk Functionality Performance Obsolescence Incompatibilities Developer Experience App startup time Test running time The bad The good Learning Standardisation Bad habits DB-Centric Quick project startup Extra work Upgrades Searching on Stackoverflow for answers Addiction