I am a PHP developer, I read about Java EE technologies and I want to implement such technologies( n-tier, EJB, JPA...) with PHP and all what coming with (MySQL, Apache...).
Don't.
PHP is not Java. Writing PHP code like you'd write Java code is silly and counterproductive. It's very likely to make future maintainers of the code want to hurt you.
Need to persist an object? Use an ORM.
Need a multi-tier architecture? If you design your code with proper separation of concerns, you've already gotten 9/10ths of the way there.
EJBs? Every time I read the Wikipedia article, they're described differently. Reusable components? With a standardized interface for what, distributed applications and data persistence? Useful, yeah, but that's not PHP. ORMs and a a good message/work queue will get the job done.
The bottom line: For the vast majority of PHP scripts, you will not need any "enterprise technologies." If you do, you're doing something wrong: either you've having overarchitected the application, or you've chosen the wrong platform.
Start by picking a modern PHP framework, and build your application from there. If you're coming from Java, then Zend Framework will seem the least foreign. Kohana, Symfony and CodeIgniter are all worthwhile. Avoid Cake for now.
Keep it simple and you can't go wrong.
Your question is an insightful one. That's because as your enterprise becomes more successful, it will have to scale up to support the load of more traffic. So you will have to separate your PHP code into layers that run on separate tiers (either separate servers or separate Virtual Machines like with Xen.)
For example, I designed a system last year implemented in PHP on 10 Linux OpenSUSE servers running about 25 Xen Virtual Machines (VMs.) Some of the VM's were load balancers, some were front end tiers, some were middle tiers and some were back-end tiers, some contained MySQL databases, and we had a couple of dedicated servers that were RAID arrays for user file storage. We created NFS mounts as necessary to save/read files to/from the RAID array.
We grouped the tiers into three related groups, so we could have independent test sites for QA, Staging (User Acceptance) and Production.
So our PHP software was separated into loosely-coupled layers as follows:
FRONT-END TIER (VMs)
Application Layer (port 80) --
including AJAX responses, validation
code, navigation, etc.
Admin layer (port 443) --
including Admin Dashboard with
access to system metrics and Unit Test harnesses
Service Provider (port 443) -- Secure
RESTful Web Services API (with token)
to provide services to Partners and
others who use the system as a
"platform."
MIDDLE TIER (VMs)
Business Logic Layer -- calculations
specific to the system or business,
or the roles and permissions for
various use cases
Interoperability Layer --
authorizations and posts to Social
networks or Partner applications,
etc.
BACK-END TIER (VMs)
Data Access Layer -- handles SQL
queries, inserts, updates, deletes to
the database (implemented as Prepared
Statements) in a way that can be
adapted when the database changes to
a different kind...example: from
PostgreSQL to MySQL or vice versa.
Includes PHP code for backing up and
restoring databases.
The idea another respondent brought up of using a Framework for enterprise software seem pretty silly to me. If you are developing a student project or a “proof of concept” on a single server, and if you already are familiar with a framework, it may have its use for rapid prototyping.
But as you see from the above, when you are writing Production-quality code, distributed across multiple tiers, you don't need the crutch of using a Framework.
Where would you put the framework to link into all the places in your code? On every tier? Bad idea. Frameworks include many pages that you may need and you may not need. So they slow down performance, especially when multiplied by every tier on which you must install them.
Equally inefficient would be to create a “layer” just to contain a framework that every other layer would have to call. The benefit of software layers is to be loosely-coupled and independent of other layers, so that when changes occur in one layer, they do not require changes in another layer.
Besides, developers who write Production-quality code don't need to rely on a “swiss-army knife” that Frameworks represent. Such developers are quite capable of writing targeted efficient code and, if necessary, reusing classes in a library they may have developed for previous projects.
Related
Can Drupal be deployed on a 3 tier server architecture (Webserver/ Appserver/ Database)?
Our database tier will have MySQL. Which tier will drupal fit in and what should be used in the remaining tier?
Yes it can.
Application Tier is basically a web node of your application. It would have a web server (Apache, Nginx) and Drupal running on it.
Data Tier would be a database node with MySQL or MariaDB. You'd just provide its IP address in Drupal's settings.php file and it will just work. You may want to add an extra node for a shared file system you would mount to /sites/default/files.
Presentation Tier is a tricky part. You may live without it (thus allowing Drupal's template system to handle the presentation - i.e. Application Tier would handle Presentation too). However, Drupal may be run "headless" - entirely as an API server, which gives you ability to write your own presentation logic (basically, an API client).
There are some interesting benefits of such a design: you may squeeze in some caching mechanism between Drupal and presentation thus eliminating Drupal's slowness. You may also easily scale Drupal instance horizontally by cloning web nodes. You may even shut down Drupal entirely for an update while presentation layer still serves cached content.
There are some interesting Headless / decoupled Drupal conference sessions out there:
https://www.youtube.com/watch?v=_GdpTwbmv0E
https://www.youtube.com/watch?v=FO6YdLQCX-w
The short answer is no.
The long answer is, since Drupal is Open Source, you can do it, with a lot of work on your part, and you would effectively be creating your own forked version of Drupal, which you would then need to maintain, because Drupal's updates would no longer work for your version.
Drupal, Joomla, and other PHP/MySQL CMS solutions are designed to be installed on a single web server, without the separation between the presentation, business logic and data access tiers that would be necessary in a true 3 tier architecture.
This means they are very practical and easy to install and use for anyone with a typical web hosting solution, but it also means they are not adequate for your typical enterprise application handling private information that needs to be protected more thoroughly, and integrated with back office applications. (Although of course they are perfectly fine if that same enterprise just wants to have an information website).
We have a pretty large Symfony 2 web application which has many different endpoints and features:
api for data from our legacy product
web components for use in our legacy product
api to our new iOS POS
api to loyalty end-user portal
web interface for loyalty end-user portal
web interface for (seperate) invoice end-user portal
big admin area with configuration for all of the above
The database layer (in Doctrine) on this is tightly coupled. Transactions from both the POS and our legacy product are used in the loyalty end-user portals and invoices are based on the same transactions. Obviously there's also many entities that are solely for specific parts of the application.
We originally decided on the single app+bundle approach for ease of programming, which has served us well in developing the whole platform. Unfortunately the main drawbacks are:
very bad performance (although things like further caching, minimizing assets etc can help, we think that having such a bloated bundle that needs to be able to handle everything and also included different 3rd-party libraries only used in specific parts of the application is slowing everything down.)
we use continuous integration and generating new builds and running all the functional tests is taking 20+ minutes.. and we still have many classes lacking (proper) tests.
when we change part of the application, another part breaks easily. Although more and more decoupling and functional tests help with that, it's still far from ideal.
I've done some research to splitting a Symfony project into multiple projects (each with it's own github) and using SOA to connect them. My personal experience so far with SOA is that it makes things very hard to test fully and adds lots of overhead when migrating from standard Symfony 2 forms (which I totally love).
I was also thinking on another solution by creating a shared bundle with the shared entities and repositories. This would make it much easier to test code and share common services (managers), although I've also heard argumentation against big managers. The big downside to this is that we cannot simply use doctrine:schema:update then, because sharing the database and updating the database on a project with a lower version of the shared bundle, will remove fields.. causing loss of data. Also on this approach I have been unable to find any examples or use-cases.. which leads me to wonder if it wouldn't have many more downsides.
So my question is: what are common approaches and solutions for splitting a big project like this? And: are there reasons that maybe it should not be split at all?
Although I'm answering your question, It's kinda hard to come with a magical solution for your problems. This is not an attempt to solve all of your problems, nor impose you of following it. This is not the only possible solution, actually this might not even solve your problems. That said, let's begin.
I'd split the project in 4 layers:
Presentation Layer: Desktop aplications, Web interfaces (no matter if
is php, C#, if it uses Symphony or any other framework and third
library components), Mobile Apps, everything end users can see and
interact with (also known as GUI). These guys only communicate with
Application/Service to request something, like a list of available
products, update some data somewhere, send an e-mail for customers.
The key here is they really don't know how and where is
Appication/Service layer going to do the requested actions.
Application/Service Layer: I'd treat this as controllers which can receive requests from the Presentation Layer, and external webservices as well. They look like APIs, and will decide if they have to access/manipulate data through a Repository, or send e-mails using some SMPT service. They just makes the communication between GUI or external webservices which might consume your APIs and Domain/Infra layers. Yet they don't actually know what SMPT service they are using, or where data is going to be stored and how (in a MySql through Doctrine? in Sql Server through Entity Framework? in a NoSql database? txt files?). Application layers usually have their own Models (also known as ViewModels), which are exposed to the world and returned to the requester (GUI or external Webservice), representing part of the domain models. This mapping (convert Domain classes to Application classes) can be done with patterns like Facade and Adapters (also called the Anti-corruption layer), and there are plenty of packages to resolve this (for C#, there is Automapper, for PHP there might exist something either). Why should you need this? To avoid exposing your full domain to the world. Suppose you have Invoice and Loyalty end-users, but you wanna treat them as one unique domain class "User" with their corresponding properties together. You could create a LoyaltyUser and an InvoiceUser classes in your application, each one containing only the necessary properties for that purpose, then use this Mapping technique to map the domain User class to each one of them. Therefore, the application layer usually contains authentication and authorization rules, so only the Loyalty end-user would have permission to access controller's actions which would deal with the LoyaltyUser model. Inside a single action in a controller, you shouldn't take different paths/ways depending on the requester (for mobile, do this, for website, do that). Instead, you might have different actions for each one, and tue Presentation layer knows what they want to request.
Domain Layer: This is your core, containing all business logic. This is what provide value to your business. Domain layer container
models/classes representing real entities from your world, interfaces
for services and repositories. Domain must be the most clean and
natural possible. They can't know what application is asking
something, nor how type of infra is being used. They just do business
logic. The Domain layer don't know if your are using Doctrine or Laravel as an ORM, nor if the application is a php website done with Symphony, or an Android Native App.
Infra Layer: Here you implement things like database, SMPT service, Logging, and other things your application might need.
Doctrine would reside here. Therefore, you would create Repository
classes implementing the repository interfaces of your domain. The
Repository implementation uses Doctrine to do stuff. These
implementations are providen to Application Layer (normally via
Dependency Injection). This means the Application Layer shouldn't
know if is Doctrine or Laravel, that's why the Application uses the
Repository (so logic to access database are encapsulated).
Your web interfaces would reside in Presentation. If the framework you use in your web have to use MVC and therefore have controllers, these controllers should dispatch to the Application Layer (I know it sounds redundant). Your APIs would reside in Application Layer.
This is very decoupled, if you need to change from Doctrine to Laravel, your don't need to change your Domain nor your Apps. If your need to change from Symphony to anything else, or even change your website from PHP to ASP or Java, your domain don't have to be changed.
Adding more layers, mapping objects, using DI shouldn't make requests slower, considering the hardware's price and capacity nowadays, the difference in time is almost imperceptible. You should put efforts attempting to improve your domain, which brings value for the business. Separating layers improve decoupling, chances of changing part of application breaking other parts, increase flexibility of scaling your app, and makes testing easier.
Rein, what was the solution you've finally ended up with? Have you actually split your project?
There is really a lack of information in this area, I just found one reasonable article https://ig.nore.me/presentations/2015/04/splitting-a-symfony-project-into-separate-tiers/
I read the article on Microservices on Martin Fowler's page and find it quite interesting. Now I plan structuring an E-Commerce Web Application as proof-of-concept and am wondering if my concept is considered being a Microservice architecture.
The architecture consists of 3 components:
a javascript based single page application, which sends AJAX requests to
a server with a REST API which feeds JSON data received by calling other services (I think you call this behaviour API Gateway)
3 services: CatalogProvider, CustomersProvider, CheckoutProvider
For now the services all are API endpoints of a Magento (PHP) Shopsystem. In future I plan to then swap the providers with other systems.
So my questions are:
MS are considered to be 'independently deployable'. I understand that in the world of JAVA we are talking about one JAR- or WAR-file, but how is a PHP service 'independently deployable'?
Does my concept NOT follow the principles of a MS architecture, because the providers are all part of one big (Magento) system?
Thank you for reading. I'm happy for any suggestions.
There is nothing that says you architecture is not a MS architecture just because you're using magento and PHP. But, you have to consider a few things:
Think in terms of always being able to rewrite any of the services in any language and deploy somewhere the total system should just continue to work.
If your services are just transformation/interface very tightly linked to magento and you cannot simply rewrite them in java/C#/ruby easily, then I guess you do not have a MS architecture.
For PHP deployable artifacts, you typically have some packaging or versioning strategy around your service. Even though "deploy" in PHP is typically just swapping a folder of .php files. And you should not really share code/config between different services. You can even look at deployment tools for PHP if you want to take an extra step.
As to the microservice architecture there is SRP principle.Single Responsiplity principle.Each service has own unique responsiplity.DB schemea shouldbe decomposed also.Exporting services as rest inside a monolithic app not convert a monolithic app to micro service application.
I'm trying to develop an application server that will deliver content to a core group of websites, as well as provide third party services to other websites that also want to use this content. The app server will be hosting web services for these core + 3rd party websites. Authentication and all that comes into play. The data itself will consist of millions of records.
These records will come from a variety of sources: APIs, RSS feeds, REST services, etc. This app server will essentially collect this data on a routine basis, and update the database with this new information. This data will then be shared via some sort of web service (most likely REST) to the core websites and 3rd party websites.
FYI, I'm making a distinction between core sites and 3rd party websites because there will be different access levels, i.e. a core website will have more access than a 3rd party website.
All that said, I'm trying to make the best decision on which framework to use. At the risk of losing all credibility, I currently have a ton of this code written as a wordpress plugin. What started as a one-time site evolved into several sites, and some homebrew hacking to make my outdated infrastructure work across multiple sites.
I'm looking to migrate all of this to a new application server, with a solid framework.
Since everything is written in PHP, obviously I'm tempted to do the migration in PHP. However, I'm considering Python because of its powerful ability to manipulate data. I don't know if it's worth the hassle, though, of rewriting a lot of code in Python.
Could anyone give me some tips on what I should do? I'm really looking to clean up a big mess more than anything, and would like a framework to encourage some solid programming conventions.
All of the frameworks that you mentioned are capable. Pick one in the language that you know the best and use that.
I agree with #gpojd's opinion. All of them that you mentioned are fully capable.
However, it looks like they are too powerful for your job. Because they are all full-stack MVC-like web frameworks shipped with ORM, Template engine, URL redirections and i18n supports.
So, I suggest you to use more lighter/thinner frameworks. and if you don't mind choosing any programming languages, please check out the below frameworks.
Python
Werkzeug : http://werkzeug.pocoo.org/
Javascript
node.js : http://nodejs.org/
with Stylus framework : http://expressjs.com/
You've probably heard of the Fat Model/Thin Controller vs. Thin Model/Fat Controller distinction. I recently heard that you can have something in between where some of the logic from the model goes into a service layer. How common is this? and do you know of (or can think of) any real examples that illustrate it?
Martin Fowler describes the Service Layer pattern of his great book Patterns of Enterprise Application Architecture. If you care about questions like the one you asked, you should read this book.
One use that comes to my mind is managing database transactions. Some people try to encapsulate starting and committing transactions in their domain models. But then they get confused when domain models invoke other domain models that also try to start and commit db transactions. So which model really gets to decide if a transaction is committed or rolled back? And what do you do if a given model is used in different ways by different clients?
The Service Layer is a solution for this, because this is the layer in which you can start and commit work that involves multiple domain models.
As for how common this is, I don't think it's common at all. Most people using Zend Framework (or any other PHP or Ruby framework) have just barely moved from "Active Record solves everything" to the new shiny, "Data Mapper solves everything." It seems this community learns only one new pattern every five years. They won't get to Service Layer for a while.
Re comment from #ktutnik:
No, the Service Layer pattern is different from Repository pattern. Repository is about abstracting database access so you can use a database like a Collection. Service Layer is about encapsulating complex application operations.
Another way of thinking about them is their relationship to the Domain Model. The Repository is used between the Domain Model and the database. Whereas the Service Layer uses one or more Domain Models.
Service Layer ---> Domain Model(s) ---> Repository ---> DBAL
Service layer advocacy is relatively new and still subject to a variety of interpretations. I think it means having a layer that leverages multiple domain models which the controllers call (I may be simplifying it too much though). I recently developed a website making use of this and practical advantages I've encountered are:
Features as a service helps with scalability. If you have an image service that initially uses the local service to do it's work it becomes easier to have that service point to another server or some 3rd party without having to make sweeping updates
Flexibility. Half way through the project I decided to change a core piece of functionality and was able to do so painlessly; allowing me to quickly weigh the pros and cons of the update. This flexibility is useful when rapid prototyping and instills a certain confidence because if you need to revisit something it's not going to be a nightmare.
Extensibility. I have already identified services in my application what I can forsee opening to other developers or other widgets, mobile apps in the future. Doing so in theory is just a matter of adding authentication and authorization to the service (because the features are already in it's own layer and I don't have to spend time trying to decouple what I want to expose from the rest of the code base).
Services are easy to add and drop (maybe this belongs with one of the earlier points). I have services that a specific to a specific stage in the project (e.g. invite only stage) that I can drop once that phase is over.
I think it has practical advantages and a key to success in implementation is having a good way to manage the services in the application. I use symfony's dependency injection component
See ZFEngine it's cmf on ZF with service layer realisation