How Was This Framework Done?

This framework initially grew out frustration with bad frameworks I used to work with then became an exercise in what can be achieved if quality and efficiency are used as fundamental building blocks.

What Were Its Goals

The main point was finally building something that is:

How Were Those Goals Met

Standing on an aesthetic foundation, framework ended up as integration tool of pluggable functionalities assembled into independent APIs, each dedicated to an aspect of a web application's logic. Framework is the ultimate assembly unit that works like a web application skeleton onto which developer assembles his code in order to have a fully working site.

Thanks to this design, it naturally achieved:

Lucinda Framework maintains simplicity of design (setup is done mainly in XML) and also makes sure no logic that is not explicitly needed will ever be ran. Taken together with absence of ORM and autowiring (massive performance killers in all frameworks), it predictably outperforms (in terms of both speed and ergonomics) any other true framework written in PHP!

Why Were Some Features Omitted

What follows below are answers to most commonly asked questions centered on framework not following "full stack standards". As a general note, framework or its composing APIs are never using abstraction for the sake of abstraction: abstraction should be a tool to achieve quality efficient code, not an end goal!

Why No ORM

Currently, querying a database via an ORM has become something like a requirement in "modern development". Using an ORM, we are told, you will be gaining an advantage in productivity (since "you no longer have to write queries"), you will abstract communication with database and you will always be ready to switch vendors (eg: MySQL to PostgreSQL) with no other move required.

Let us examine more on these advantages:

Now let's examine on untold disadvantages:

The final conclusion is that ORMs only look good on paper. Whenever they are applied, you are guaranteed to have a slow software (unless caching is used) and a chaotic product (thanks to developers not learning it properly). A far better solution, recommended not just by this framework, is to employ Entity/DAO pattern without automated persistence (ORM):

Why No Autowiring

Although this is not a de-facto requirement, all highly acclaimed frameworks use a dependency injection container to autowire objects into user classes, such as controllers for example. Let us compare Laravel's to base controllers to understand the differences:

This feature brings some advantage in development speed to frameworks using dependency injection container (some lines less code), but performance will again suffer a lot because of the magic former needs to do behind the scenes. Furthermore, in author's view, dependencies should be explicit: presence of unseen relationships makes code difficult to follow, decouple or test.

Why No Controller Actions

Most, but not all, frameworks split a controller's logic into "actions". This is the equivalent of namespacing requests: one controller handling one or more requests, each with its own processing logic. Lucinda omits them entirely because:

Why No Classic Template Inheritance

The templating engine used by Lucinda, View Language API, is strictly working like an extension of HTML. In HTML, keyword "extends" makes no logical sense: the only thing you have are views, themselves recursively composed of templates! How to react when two or more views share templates then? Lucinda solves this problem by dynamically loading templates based on recipe-ingredients principle.

This works in a way similar to dependency injection: instead of EXTENSION (which brings up rigidity to the structure) you opt for INJECTION (which makes constituent structures light and maintainable). This way, an item can "inherit" many behaviors, which is actually a fundamental requirement in HTML templating.

Let's say for example you have an HTML application where every page shares a common header and footer while at the same time holding a body component that is page-specific. You first need to create tag <site:page> holding master template with following body:

<site:header .../> <$[body] .../> <site:footer .../>

where $[body] on compilation will be replaced with page-specific template. Every view using master template above will only have a single line where above tag is invoked, setting $[body] to match page-specific template tag. Example that points to <site:homepage> that will contain homepage-specific template logic:

<site:page body="site:homepage" ... />

Since compilation is recursive, the same "inheritance" principles can apply at infinite levels. You can have pages that contain MULTIPLE recipe tags, themselves composed of fixed (like site:header tag above) and mobile(like site:homepage tag above) tags, themselves pointing to recipes or implementation.

Why No Autoload Until Version 3.0

An extremely common criticism to Lucinda Framework 2.0 was absence of autoload. This is a requirement of PSR-4 standards and author decided to skip it because of performance penalty that comes along with it. You were demanded to manage resources manually (via require), as all other programming languages do, and that made framework exceptionally fast. However, following problems ensued:

As a measure to popularize framework and keep it more in line with "standards", autoloading was reluctantly activated (going against good principles) in Lucinda Framework 3.0 and it brought an expected 15% performance penalty. It was simply considered that framework was fast enough to leverage some of its performance to increase development speed!

×