Skip to main content

Web Application Development following Functional Programming Principles

After studying category theory and functional programming, I decided to put these concepts into practice by developing a simple web application. This project was inspired by the example in Chapter 11 of 'Programming in Haskell' by Graham Hutton. My goal was to take these theoretical programming ideas and see how they work in creating a real-world web application.

The key concepts of functional programming are:

  • Prioritize creating pure functions as much as possible. These are functions without side effects, making them simpler to test

  • Use composition of pure functions to construct more intricate functions

  • Use Functors, Applicatives, and Monads in scenarios that require pure functions, such as error handling or managing missing values, and when working with collections like trees and lists.

I wrote this application in Java, utilizing the Spring Boot framework. This decision was influenced by my previous work in developing enterprise applications with this technology stack. My objective was to investigate how functional programming (FP) concepts and techniques could be effectively applied in a real-world Java application. While Haskell, TypeScript, or React JS were potential alternatives, my goal was to create a project that was more than just a theoretical example, but rather one that had practical relevance to my professional work.


I also wanted to explore a few ideas beyond the typical development toolkit. I've been in search of a rendering framework that is both strongly typed and easily composable. The current state of the industry for Spring Boot is to use Thymeleaf as the template framework. I used Thymeleaf, and several other template libraries, in several projects but I see several drawbacks:

  • Separate HTML file: Initially easy to write but becomes challenging to maintain

  • No layout template model: Requires importing a separate library, adding more XML elements and attributes

  • Not strongly typed: Becomes error-prone over time.


This led me to explore Java-based DSLs (Domain-Specific Languages). Initially, I tried htmlflow, but eventually, I decided on J2HTML. I was looking for a commercial, predefined Admin Layout that simplifies development. This approach ensures that essential widgets, like forms, buttons, and alerts, are readily available, without the need for a deep dive into CSS/JS. Lately, I've been using Core UI (coreui.io), which is built on the Bootstrap framework but offers additional widgets ideal for medium-complexity enterprise applications. For my demos, the free version of Core UI suffices, and for full-scale applications, I use the pro version. Its extension of widgets is useful for developing enterprise applications of moderate complexity.

Design of the Game Engine

The Game Engine closely follows the [PiH] design. The Java classes correspond to Haskell types:

  • Player an enum in Java, a type in Haskell. A bit more involved in Java because there is a conversion from an enum to char which is implicit in Haskell. Another interesting point discovered is that Java enums implement Comparable with the natural order based on the order in the source code, which is similar to Haskell

  • Grid is a class in Java and a type in Haskell. Most operations convert nicely from Haskell to Java. I used streams instead whenever possible

  • All public operations in the Grid class are pure-function, with the convention that the object itself (this) is the first parameter in all operations.

  • GameNode, GameTree are classes in Java. There are no Haskell types for it but probably should for clarity. The public methods of these classes are pure functions.

Design of the User Interface

The user interface relies on Spring MVC. Controllers process requests, interact with services like our Game Engine and prepare views.

I used high-level views based on page templates, each with specific panels. For example, the T3PageTemplate renders the grid in a two-panels layout. This layout includes navigation links, user info, a right column card, and associated JS scripts. 

A page in the application is a dynamic ensemble of various elements – widgets, text, images, and links – all coming together to present a rich and complex dataset. Consider, for instance, the page that renders the grid. It's not just about displaying the grid; it also incorporates the brand, user information (whether the user is authenticated or not), and a user-dependent menu. You might imagine a class, GridPageView, with a render method that takes in all the necessary data for display. This method would then orchestrate various sub-views like HeaderView, SideBarView, and GridCardView, each with their components like UserView, GridView, MenuView. However, a challenge arises with this structure: it necessitates defining methods with extensive arguments. Moreover, if a nested widget requires a new data piece, it calls for modifying all the methods upstream, making the process cumbersome and less efficient.

Conclusions

I started this project aiming to apply category theory and functional programming concepts to developing web applications in Java. Did we meet these goals?

  • Application Completion and Functionality: I successfully built a working Tic-Tac-Toe application. It closely follows the logic of its Haskell counterpart, achieving our primary objective

  • Use of Functional Programming Concepts: The outcome here is somewhat mixed. I incorporated a significant number of pure functions, primarily as Java static methods or non-static methods not tied to shared objects. This strategy resulted in classes having many small static functions, an approach not typical in Java where non-static methods are often preferred for their override-ability in subclasses. This method minimized the use of subclassing, aligning with functional programming principles

  • Class Design and Methodology: Ultimately, our classes consisted either of static methods or instance methods when implementing an interface. This distinction highlights the functional programming approach within the Java framework

  • Constraints and Differences Relative to Haskell: There are features in Haskell, like currying – the conversion of a function with multiple parameters into a series of single-argument functions – that Java does not directly support.

For my next project, I plan to investigate further into several areas highlighted by this exercise:

  • I'm going to examine the concept of 'View' as a Functor. In this context, for any business object X, a View<X> would be its representation in the user interface. I'm interested in seeing how compositions in the business domain translate into UI compositions

  • Another direction: considering the preference for aggregation over inheritance, I'll explore how the design pattern “Builder” is used to create intricate UI components.

Popular posts from this blog

View - A Functor for Web App Design

This blog is about practical applications of Category Theory to the development of Java + Spring applications. I am looking at a design approach to simplify the development of web applications. Traditionally, this kind of back-office application is based on the Web 1.0 technology stack, using Spring Boot and Thymeleaf. My approach is to keep using Spring Boot but replace the generation of HTML with J2HTML and higher-order views. From a Category Theory point of view, we can look at web applications as mappings from the Category of Business Entities and the Category of UI Widgets. If we go one step further, both business entities and UI widgets are mapped to Java classes. Thus, we can view a web application (or a part of it) as an endofunctor in the Category of Java Classes. We define the View-functor as follows: domain(V) - Java classes representing business entities - e.g., Invoice, User - and, codomain(V) - Java functions that render the business entity as a DomContent object (DomCont...

Reading J2HTML

J2HTML (j2html) is a Java library used to generate HTML I have been using it to create Web 1.0 applications in Java. Web 1.0 is server-side rendering pages with minimal Javascript. As I got deeper into using the library I started to read the actual source code of this library with an eye on following Java best practices and to my pleasant surprise, this code follows many of them. I am going to show here some examples of using interesting Java features, beyond the basics. 1. Functional Interface People are aware that Java supports some form of Functional Programming, and here is an example of using it: @FunctionalInterface public interface Indenter {     String indent( int level , String text ); } public static Indenter indenter = ( level , text ) -> String. join ( "" , Collections. nCopies ( level , FOUR_SPACES )) + text ; Things that I noticed: String has a method called join. I used before StringUtils.join, but now that is in the standard library I don’t n...