Developing Web Application Without any Framework

Recently while I got an opportunity to mentor young budding engineers for a project I was about to lead. I was excited and took the initiative to set up a discussion regarding each one thought and idea about solving the problem.

I realized that most junior developers who have interned and only seen web application side of development lack the understanding of fundamentals like :

  • What is that the framework provides?
  • Difference between application code and cross-cutting concerns?
  • How do you break and bundle application into modules?

Each coming from a different framework background (Spring, Dropwizard, Django) some even from other languages have almost orthogonal ideas about the responsibility of classes modules and even the design. From my perspective answering each question and removing each doubt is like only polishing scratches of a broken car. I quickly realized and answering each question and doing PR review would become very tiresome and a lecture for each of us.

So I thought of creating this new application without any framework, I believed that it would take the same time to gather everyone to work on a particular framework than to let go of benefits of framework and in effect teach everyone by practical example.

The best part was when is when you break the news about not using any framework at all. Instantly the minds of those build on framework goes in vertigo and the real questions come out.

  • How to map HTTP requests to our functions?
  • How will we enable metrics?
  • How will we describe the controller and views?
  • How will connect to the database?

I can see the fundamentals questions start popping up the very strike that what if there were no frameworks? This was great, I wanted these questions to be raised and asked to find out themselves.

I purposefully let each piece go to one person and explain their solution to the team so that each can learn and understand one part of application design. I separated the application into logical modules stating their responsibility.

  • CORE: All interfaces that segregate responsibility will come here like
    • All dtos that flow within the system are objects that all services interact with.
    • Persistence
    • Cache
    • Other application design specific responsibilities.
    • CoreService – this is the collection of services exposed through the server.
    • CoreImpl – here goes the business logic, for all the APIs and are only written in terms of the interfaces present in the core.
  • SERVER: This modules only deals with
    • Instantiate application code
    • REST resources
    • Webserver support
    • Serialization
    • Metrics
    • API spec
    • This module only uses the CORE interface to call all exposed services.
  • CORE-IMPL-MYSQL-GAUVA CACHE-ELASTIC: all implementation except the core will be defined here:
    • Hibernate specific code for Persistence Service.
    • Elastic specific code for Search Service.
    • Simple guava cache for caching
  • CORE-IMPL-MOGO-REDIS-ELASTIC: all implementation except the core will be defined here:
    • Morphia (Mongo) for Persistence Service.
    • Elastic specific code for Search Service.
    • Redis cache for caching
    • This was important to demonstrate good design system that if properly abstracted can switch the underlying implementation without impacting business logic or server-side code.
  • MODELS: This module deals with all classes that are to be exposed outside the system for other services to interact with this application.
    • All Request Responses classes.
    • Builders and Helpers.
    • Clients
  • Commons: This module deals with commons code required across modules.
    • Exception constants
    • Other constants
    • Serdes
    • DTOs

Then some guidelines and principles to be followed were that :

  • Code to interfaces: Only interfaces are to be coded to and no direct implementation class to be used.
  • Do not break the abstraction: No one person/implementation should write code that requires information about another interface’s implementation. Always respect the interface.
  • Do not create new functions in an interface that was not part of the group discussion.

This exercise cleared up confusions like library vs framework, jersey vs REST, hibernate vs JPA, and also taught the benefits of framework just the hard way.

When people started this understanding and building real concepts ground up I felt great and can see the application building nicely and each team member understanding concepts rather than just code.

TThe next challenge was testing of which everyone was least concerned. However to spark interest, I create a new TEST-MODULE while uses only mocked the external clients and supplied with in-memory DB, and the whole server could be tested just like a running server. This was facilitated and a validation of the good design and test-ability of the code. This excited each to write both unit and integration test cases, catching a lot of bugs early on.

This small happy moment was quickly over until the new concerns started popping up which puzzled everyone. Questions like :

  • Where should the transaction begin? server, core or persistence?
  • Logging for each module separately? how to configure level for all the application?
  • The configuration will be provided or each module should carry their own?
  • Exception handling will be done on server/core/implementation?
  • How to have consistent documentation?

These are really good insights this is when people break the mental models and hits the wall of what the framework invisibly was providing. I explained cross-cutting concerns and it took a long time for me to resolve this without having actually built a framework of our own. This took some time however the end result was strong-headed people with deep understanding and appreciation for web application frameworks.

This whole experience removed the mystical powers of most commonly used annotations like –

  • @Autowired @Inject -> magically give what you need.
  • @Transactional -> no thoughts given.
  • @Log4j / @Slf4j ->cannot log if this is not present.
  • @Timed @Meterd -> magically created graphs

Clearing this hurdle was enlightening and blissful. Note that this is the piece of code that absolutely did not have any impact on logic, performance or anything from a business standpoint. However, the whole experience and journey were really enlightening for the whole of the team. I think this was of great value as it created better engineers for the organization.

Leave a Reply

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Catch Me On Social !!