Using phploc for a quick code quality estimation - Part 2
In part 1 of this series we discussed the size and complexity metrics calculated by phploc. We continue with a discussion about dependencies and structure.
Structure
This section gives us an idea of how many things there are of a certain type. These can be useful indicators too. For example, if the number of Namespaces is low, there may be a lack of grouping, which is bad for discoverability. It’ll be hard to find out where a certain piece of logic can be found in the code. Too many namespaces, relative to the number of Classes/Interfaces/Traits, is not a good sign either. I would expect every namespace to have a couple of classes that naturally belong together.
Using phploc for a quick code quality estimation - Part 1
When I want to get a very rough idea of the quality of both code and structure of a PHP code base, I like to run phploc on it. This is a tool created by Sebastian Bergmann for (I assume) exactly this purpose. It produces the following kind of output:
Directories 3
Files 10
Size
Lines of Code (LOC) 1882
Comment Lines of Code (CLOC) 255 (13.55%)
Non-Comment Lines of Code (NCLOC) 1627 (86.45%)
Logical Lines of Code (LLOC) 377 (20.03%)
Classes 351 (93.10%)
Average Class Length 35
Minimum Class Length 0
Maximum Class Length 172
Average Method Length 2
Minimum Method Length 1
Maximum Method Length 117
Functions 0 (0.00%)
Average Function Length 0
Not in classes or functions 26 (6.90%)
Cyclomatic Complexity
Average Complexity per LLOC 0.49
Average Complexity per Class 19.60
Minimum Class Complexity 1.00
Maximum Class Complexity 139.00
Average Complexity per Method 2.43
Minimum Method Complexity 1.00
Maximum Method Complexity 96.00
Dependencies
Global Accesses 0
Global Constants 0 (0.00%)
Global Variables 0 (0.00%)
Super-Global Variables 0 (0.00%)
Attribute Accesses 85
Non-Static 85 (100.00%)
Static 0 (0.00%)
Method Calls 280
Non-Static 276 (98.57%)
Static 4 (1.43%)
Structure
Namespaces 3
Interfaces 1
Traits 0
Classes 9
Abstract Classes 0 (0.00%)
Concrete Classes 9 (100.00%)
Methods 130
Scope
Non-Static Methods 130 (100.00%)
Static Methods 0 (0.00%)
Visibility
Public Methods 103 (79.23%)
Non-Public Methods 27 (20.77%)
Functions 0
Named Functions 0 (0.00%)
Anonymous Functions 0 (0.00%)
Constants 0
Global Constants 0 (0.00%)
Class Constants 0 (0.00%)
These numbers are statistics, and as you know, they can be used to tell the biggest lies. Without the context of the actual code, you can interpret them in any way you like. So you need to be careful making conclusions based on them. However, in my experience these numbers are often quite good indicators of the overall code quality as well as the structural quality of a project.
Dividing responsibilities - Part 2
This is another excerpt from my latest book, which is currently part of Manning’s Early Access Program. Take 37% off Object Design Style Guide by entering fccnoback into the discount code box at checkout at manning.com.
Make sure to read part 1 first.
Create read models directly from their data source
Instead of creating a StockReport
model from PurchaseOrderForStock
objects, we could go directly to the source of the data, that is, the database where the application stores its purchase orders. If this is a relational database, there might be a table called purchase_orders
, with columns for purchase_order_id
, product_id
, ordered_quantity
, and was_received
. If that’s the case, then StockReportRepository
wouldn’t have to load any other object before it could build a StockReport
object; it could make a single SQL query and use it to create the StockReport
, as shown in Listing 11).
Dividing responsibilities - Part 1
I’m happy to share with you an excerpt of my latest book, which is currently part of Manning’s Early Access Program. Take 37% off Object Design Style Guide by entering fccnoback into the discount code box at checkout at manning.com.
Chapter 7: Dividing responsibilities
We’ve looked at how objects can be used to retrieve information, or perform tasks. The methods for retrieving information are called query methods, the ones that perform tasks are command methods. Service objects may combine both of these responsibilities. For instance, a repository (like the one in Listing 1) could perform the task of saving an entity to the database, and at the same time it would also be capable of retrieving an entity from the database.
You may not need a query bus
“Can you make a query bus with SimpleBus?” The question has been asked many times. I’ve always said no. Basically, because I didn’t build in the option to return anything from a command handler. So a handler could never become a query handler, since a query will of course have to return something.
I’ve always thought that the demand for a query bus is just a sign of the need for symmetry. If you have command and query methods, then why not have command and query buses too? A desire for symmetry isn’t a bad thing per se. Symmetry is attractive because it feels natural, and that feeling can serve as design feedback. For instance, you can use lack of symmetry to find out what aspect of a design is still missing, or to find alternative solutions.
Learning Laravel - Observations, part 1: The service container
With excerpts from the documentation
I have worked with symfony 1, Symfony 2+, Zend Framework 1, Zend Expressive, but never with Laravel. Until now. My partner was looking for a way to learn PHP and building web applications with it. Most of my own framework knowledge is related to Symfony, so my initial plan was to find a Symfony course for her. However, Jeffrey Way’s Laracasts also came to mind, and I thought it would be an interesting learning experience for us both if Laravel would be the framework of choice in this matter. It turned out to be a good idea. My partner is making good progress, and I get to see what Laravel is all about. We have a lot of fun together, finding out how it works, or what you’re supposed to be doing with it.
Newcrafts 2019 Day 1
This week I attended and spoke at the Newcrafts conference in Paris. The following is a mix of notes and personal observations I wanted to share, centered around some of the talks I saw there.
Romeu Romera: Bourdieu’s Social theory and our work in tech
I had never attended a talk by Romeu before. I really enjoyed this one. Somehow I already knew that he uses a mindmap to support his talk. I thought he would use an existing mind map to navigate through the talk, but it turned out he was creating one during the talk. For me personally, a slide deck helps to keep track of the story, and it helps me remember all the different topics I need to talk about. Not so much for Romeu, who knew exactly what he was going to talk about, and didn’t seem to forget to mention any important part, or make important connections.
Style Guide for Object Design: Release of the PHP edition
With a foreword by Ross Tuck
Today I’ve released the revised edition of my latest book “Style Guide for Object Design”. Over the past few weeks I’ve fixed many issues, smaller and larger ones. Ross Tuck and Laura Cody have read the manuscript and provided me with excellent feedback, which has helped me a lot to get the book in a better shape. I added many sections, asides, and even an extra chapter, because some topics deserve more detail and background than just a few paragraphs. Oh, and Ross wrote the kindest of forewords to kick off the book. It’s available in the free sample of the book.
Hand-written service containers
You say "convention over configuration;" I hear "ambient information stuck in someone's head." You say "configuration over hardcoding;" I hear "information in a different language that must be parsed, can be malformed, or not exist."
— Paul Snively (@paul_snively) March 2, 2019
Dependency injection is very important. Dependency injection containers are too. The trouble is with the tools, that let us define services in a meta-language, and rely on conventions to work well. This extra layer requires the “ambient information” Paul speaks about in his tweet, and easily lets us make mistakes that we wouldn’t make if we’d just write out the code for instantiating our services.
DDD Europe notes - Day 2
Cyrille Martraire: Domain modeling towards First Principles
This was a talk from the first day, but it required some more processing before writing about it. Cyrille is one of my favorite speakers. He’s fast, funny and brings a lot of interesting topics to the table. So many that it’s sometimes hard to keep following his train of thought, and writing down some notes at the same time.
A central concept from his talk was what he called the waterline between IT and the business. In a traditional scenario, developers get provided with “work” on a case-by-case basis. They don’t learn about the general idea or plan, or even the vision, goal or need that’s behind the “work item”. They just have to “implement” it. It leads to badly designed code. But it also leads to the wrong solutions being delivered. If only developers could have talked with the people who actually have the problem for which they build the solution. Maybe there’s another problem behind it, or maybe the business has provided the developer with a solution, instead of a problem. To higher the waterline means to get more involved with the customers and users, to understand their problems, and work together on a solution. Make sure you get involved.