Posts

Showing posts from 2017

The Role-In Stone (part I)

Image
Hello, There are always times during our journey as developers when we need to handle responsibilities according to several user roles, eg admin vs regular user privileges and so forth. This has been my case lately. I’ve been asked to implement a role based management tool which had to handle Administrators and Players by creating slightly different layouts for each one and paying attention to subtle differences on specific functionalities. My very first try consisted of url driven request and shared templates in order to detect and display the roles accordingly. Sooner than later, as the functionalities grew, many if-else structures sprouted all across the code, littering and degrading the code significantly. My next step was to refactor and plan a unique if-else at the earliest stage to detect the role, and then, use a service handler to deal with the specific role. As a result, I had a role factory which was initialized with the user and returned the corresponding r...

Legacy code concepts II: the Seam Model

Hi audience, According to my last post, there are some important concepts related to legacy code that it is worth writing down and, therefore, have a clearer picture. Sensing and separation were two of them, both concepts tightly related to breaking dependencies. Moving forward, in line with those, I’m going to write about the Seam Model, introduced by Michael C. Feathers in his book Working Effectively with Legacy Code . The Seam Model The Seam Model is a convenient name to represent the ways by which we can perform tests without producing code changes in order to get a class into a test harness. A Seam Quoting the author, “A seam is a place where you can alter behaviour in your program without editing that place” Important to highlight: alter behaviour without editing . So how can we change behaviour without changing the code? We can actually do it in different ways or manners so far: Seam types Preprocessing seam : used in languages that allow preprocessing, such as C+...

Legacy code concepts I: Sensing and Separation

Hi again, I’ve been lately reading my last technical book acquisition: Working effectively with legacy code (Michael C. Feathers) and, after several chapters, I’ve decided to write down some key concepts in order to make them clearer on my mind. Context The book is mainly focused on how to get a class into a “ test harness ”, or, in other words, how to  successfully create unit tests for legacy code so the risk of side effect changes is minimized. Usually, in order to get a test harness, dependencies between classes must be broken, hence, some code refactors are put in place, this situation leads to a potential vicious circle scenario: A change -> test harness -> break dependencies (refactoring) -> A change Breaking dependencies is the cornerstone of the whole strategy for getting a class into a test harness. However, the solution is, as we already know, quite difficult to implement sometimes, so, in order to tackle such challenge, the author proposes a v...

Bulk Inserts and the Performance Holy Grial (Part II)

Hi, Back to our topic ( see previous post ) about bulk inserts using PHP and Oracle OCI library, the first approach I'll explain today is as follows: Public method bulk_insert public function bulk_insert($common, $data) { try { $params = $this->prepareBulkInsertParams($common, $data); return $this->ociBulkInsert($params); } catch (Exception $e) { $this->logger->log(ERROR, $e->getMessage()); } } Neat, isn't it? At a first glance, a much clearer method is the result of a first refactor. Many of the code pieces have been extracted to a new method ( Extract method , Refactoring, K. Beck) alongside with new ones to give support to the PL/SQL batch insert syntax. Preparing the Parameters This method is just for extracting the incoming data and transform it into a more manageable array. private function prepareBulkInsertParams(array $common, array $data) : array { ext...

Bulk Inserts and the Performance Holy Grial (Part I)

Hello, I've been asked to improve a part of a model class which is causing some database issues. We use PHP and Oracle, so our legacy code is built using the OCI ( Oracle Client Interface) built-in library to take advantage as much as possible of the driver speed instead of using either the CodeIgniter abstracted database class or, simply, PDO ( PDO for Oracle ). Since we have to deal with bulk transactions under high load scenarios, database access optimization is a must. Massive rows have to be inserted prior to another batch of updates on them lately. Binding parameters in advance is a way of getting a performance improvement (read more on this topic here: https://blogs.oracle.com/sql/entry/improve_sql_query_performance_by ), in addition to avoid SQL injection attacks. So, here's is a snippet of what the bulk insert method looked like before any change: class TxnUser extends CI_Model { const OPEN = 1; const CLOSED = 0; [...] // Legacy meth...

Pride & Punishment

Image
Hi there, It's Friday and we all get relaxed at work before officially starting the weekend. No releases or any changes that could potentially cause any bothering or major problems. We're all euphoric and you can nearly feel yourself sat in a terrace bar having a fresh (spanish) lager with some tapas, enjoying the enviable weather of Majorca (my apologies if u live in rainy, cloudy, northern European country xD, I'm being mean now).  A teammate is about to commit his last change and prepare a Pull Request for the next release, and, finally, off he goes: Notice the name of the PR. I can assure you that the guys of the company next to us could hear us laugh out loud for a while.  Let me put you in context regarding this PR and the project to which is related. The PR code belongs to a relatively young project (almost 2 years old) that was born, in my honest opinion , with several mistakes. First and foremost, no unit tests at all, unbelievably, nowadays,...

And eventually, we're done. (Part III of 'Yes, you can' series)

In our previous post , the parent class CITestCase was shown, now it's time for the concrete ones. A Test Case This class shows very briefly how to define the test case and how to organise assertions. final class AttemptsModelTest extends CITestCase { private $model; protected function setUp() { $this->model = new AttemptsModel(); } protected function getLastAttemptTest() { $ok = true; $fixtures = [ [ ['msisdn' => '525531783674', 'id_service' => '2210'], // Fixture ['id_attempt' => '456'], // Expected ], [ ['msisdn' => '94000000000', 'id_service' => '1930'], ['id_attempt' => '103005514'] ], ]; while (($fixture = array_shift($fixtures)) ...

Yes, you can, part II

Hi, Following the previous post topic regarding building your own solutions when using a package or framework is not an option, I proceed to show how CITestCase looks: The Unit Testing bespoke solution abstract class CITestCase { private $printer = null; public function __construct(OutputPrinter $printer) { $this->printer = $printer; } abstract protected function setUp(); abstract protected function tearDown(); public function run() { $results = []; $me = new ReflectionClass(get_called_class()); $batch = array_filter($me->getMethods(ReflectionMethod::IS_PROTECTED), function(ReflectionMethod $method) { return preg_match('/Test$/', $method->getName()) === 1; }); /* @var $testMethod ReflectionMethod */ foreach ($batch as $testMethod) { $this->setUp(); $results[] = ['name' => $testMethod->getName(), ...

Yes, you can!! Part I

Image
Hi there, Does it ring a bell those situations where you need a new functionality for your code and you cannot use third party software straight off?  A quick assessment along with a decision has to be made quickly in order to either doing something from the scratch (in a decent time) to fit the needs, or go through a tough process of adapting the legacy old code base to make it compatible with the third party system. Both situations imply risks and you have to reach a trade-off depending on the context. By and large, we are so used to rely on frameworks and packages that encapsulate some kind of feature, that we become lazy when it comes to build something we know it already exists, so our first approach is to try to adapt.  Since  CodeIgniter  (CI) turns out to be unfriendly in terms of testability, adopting the  PHPUnit framework  becomes an unpleasant task. Given my company current context, going through a massive change of the frame...

"I'll be back later, I'm sure I will"

Image
Hi, Today, when I was revising some classes of our messy code base, it caught my attention this comment of one of my former teammates, who recently left: Back in June 2016, when he was actually performing a refactor of the same code base, he wrote TESTS PENDING into a commit, bearing in mind to create some unit tests after the refactor. Unfortunately, we know we never come back. And this is something we all have gone through. Some of the important bits that Martin Fowler and Kent Beck encourage to do when performing refactors of legacy code is to move on bit by bit, small changes along with unit tests. [ Refactoring ] After a massive refactor, they also point out, it's very difficult to keep track of all the changes in case we break the code, and as a consequence, reverting our changes is necessary. Performance gains when shorts steps are taken since we minimise the time of reverting newly introduced bugs or rolling back due to undesired side effects. In short...

Introducing myself

Hi there, It is my aim to write a series of articles based on my personal experience on programming from now on and, why not, maybe from my past as well, about coding and related activities. The approach I'd like to take is about experiences, either good or bad ones. And about any interesting code snippet I may have come up or come across. My linkedIn introduction My name is VĂ­ctor Molero, 40yo, father of two children. I'm passionate about building (or refactoring) software to a high quality standard by using proven good practises. My background is made up of a Computer Science Bachelor, 15+ years of experience working with a wide range of technologies and a special care to the detail on my day by day work. LinkedIn profile:  https://www.linkedin.com/in/vicjmt/?locale=en_US Thanks I'd like to thank  Sandro Mancuso , whose book " The Software Craftman ", enlighted me to start writing for the community to spread my (little) wisdom. Spreading ...