Sunday, 12 January 2025



 Another code snippet to run Java JUnit quickly from the command line:

(Assuming you have download Java SDK, and add JAVA_HOME to your PATH variable)

1. You have downloaded the Maven binary zip and extracted it to your local folder e.g Program files

2. Add the `bin` folder of the Maven folder to your PATH

3. Create a project folder called this `Testing`

4. Inside "Testing" folder, create two folders, one for your Java code files and another for your Test files. For the Java files folder, create `src\main\java`. for testing files create `src\test\java`. By putting the files inside  the `java` folder, the test files can use the Java classes without using any import, and both will be on the default namespace. 

5. put pom.xml inside "Testing" folder, the pomxl should import the Junit

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>my-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!-- JUnit 5 Dependencies -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Maven Surefire Plugin for running tests -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M5</version>
                <configuration>
                    <includes>
                        <include>**/*Test.java</include>
                    </includes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

5. Open the command line or terminal in the "Testing" folder, and run "mvn test"



Tuesday, 7 January 2025

Debugging configuraiton for react project


Just drop some writing for react debugging. I have done this before, but keep forgetting some details when moving to a new environment again. So here we are:

Assumption:

* A React project in node.js project (usually writing in typescript and with webpack configuration)

* The client is WPF using webview2 to host the react website.


1. Produce the source map for the project files

React code is transpiled (from JSX and Typescript code) into a Javascript before being downloaded into the client (web browser, or webview2 in WPF). For debugging, a source map need to be produced and downloaded to the client as well. So, the first step is to generate a source map for the server. The quickest way to run webpack-dev-server, which can be configured in package.json:

"start": "webpack-dev-server --mode development",

When the `webpack-dev-server` is run in development mode, the source map will be inlined in the JavaScript code downloaded, or we call this mode  `eval-source-map`. 

There are multiple ways how to generate a source map through the `devtool` attribute in the `webpack.config.js`; you can google it and find the different values you can assign to this attribute. Running the dev server is equivalent to setting this attribute to  `eval-source-map`, which is not a full mapping but allows fast map generation.

2. Client-side debugging
For the client side, you can install the React Developer Tool on Chrome or Edge; that way, you can debug in the browser by opening Developer Tools in Chrome debugging. If your client is WebView2 inside WPF, you can enable DevTools so you can access the debugging functionality like in the web browser. 

   WebView.CoreWebView2.Settings.AreDevToolsEnabled = true;

or you can make the browser

In the Chrome DevTools, you should see something like this, in which you can put breakpoints etc, to debug.





3. Attach the browser to the VS code. 

Alternatively, you can debug directly from VSCode, but make sure you debug in the browser first to ensure all prerequisites are met.

To debug in VSCode, you need create launch configuration in .vscode, here's is the example of create launch configuration for edge, chrome, and webview2/

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
       
        {
            "name": "Launch Chrome",
            "request": "launch",
            "type": "chrome",
            "url": "http://localhost:3006",
            "webRoot": "${workspaceFolder}/src",
            "sourceMaps": true,
            "trace": true,
        },
        {
            "type": "msedge",
            "request": "launch",
            "name": "Launch Edge against localhost",
            "url": "http://localhost:3006",
            "webRoot": "${workspaceFolder}/src",
            "sourceMaps": true,
            "useWebView": true
        },
        {
            "name": "Attach to WebView2",
            "type": "chrome",
            "request": "attach",
            "port": 9222,  // Default debug port for Chrome (WebView2)
            "webRoot": "${workspaceFolder}/src",
            "sourceMaps": true,
            "url": "http://localhost:3006"  // URL where React app is served
        }
    ]
 }








Tuesday, 19 December 2023

PHP DB Migration with Phinx



Hi, see you again here I will write about my experience working with PHP migration scripts. To make the story short, I was involved in a project working on a PHP application project. The team is new to bitbucket, migration scripts, and CD/CI. So part of the job was to introduce these topics to them. Though PHP is not my regular tech stack, I found it pretty similar to Node/Javascript and Python stacks. npm in Node/Javascript, pip in Python, and composer in PHP.  The learning curve is very short and easy, as there is a code base to learn from. Just need a couple of days to be productive, as the same OO principles apply. In this article, I will write my experience using PHP migration scripts using Phinx. 

Working with migration script is not new to me, as I have used it all the time in dotnet and C# stacks using Microsoft Entity framework.  The working principles are the same in Phinx. 

Here are several assumptions before we start:
  • I work on WINDOWS 10 operating system
  • I used Vscode and its terminal,
  • I have downloaded and installed PHP, Make sure path to PHP is set in the PATH environment
  • I have downloaded and installed Composer (PHP package manager). Make sure the path to Composer is set in the path environment
  • I have installed MySQL with username: root, password: admin
  • I run command line (not bash , nor powershell)
  1. Create a project folder. eg. called MyApp
  2. Open the folder using VSCode
  3. Open a command line terminal
  4. Install phinx using composer by running: composer require robmorgan/phinx
  5. The command will create composer.json, and composer.lock, and also package folder called vendor.  The composer files are to manage packages for the project. The The package and all its dependencies will be contained within the vendor folder. The executable is placed the inside vendor/bin (the phinx command). See the pictureelow


  6. The whole folder of vendor folder can be copied to another project if all you need just the migration scripts and you don't need the composer. Phinx can be installed system-wide like the composer, but when porting the app to another machine, the command will be lost, and we need the command to be embedded in the application bootstrap. 
  7. Now every time you want to run migration scripts, you need to execute 'vendor/bin/phinx'. To make this shorter in the VSCODE terminal, you can set the variable in the
    • select File->Preference-Settings, and 
    • type: terminal.integrated.profiles.windows,and on the right panel, 
    • click on Edit in settings.json. 
    • create a new element call PATH, and fill the value with computer PATH in addition to phinx folder ".\\vendor\\bin" 
    • reopen a new command line terminal in VSCODE, and you can type "phinx" directly, however, when you want to incorporate the command in the app bootstrap you will still need to use the relative path which is 'vendor/bin/phinx". But for the development, we can use phinx command directly. 
  8. You can run 'phinx' command to see what command you can use. For data migrations, we will need this command
    1. init
    2. create
    3. seed:create
    4. migrate
    5. seed:run
    6. status (usefull to see what migration has been applied to DB)
  9. To initiate migration, first run: phinx init 
      • This command will create phinx.php in the root folder. 
        <?php

        return
        [
            'paths' => [
                'migrations' => '%%PHINX_CONFIG_DIR%%/db/migrations',
                'seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds'
            ],
            'environments' => [
                'default_migration_table' => 'phinxlog',
                'default_environment' => 'development',
                'production' => [
                    'adapter' => 'mysql',
                    'host' => 'localhost',
                    'name' => 'production_db',
                    'user' => 'root',
                    'pass' => '',
                    'port' => '3306',
                    'charset' => 'utf8',
                ],
                'development' => [
                    'adapter' => 'mysql',
                    'host' => 'localhost',
                    'name' => 'development_db',
                    'user' => 'root',
                    'pass' => '',
                    'port' => '3306',
                    'charset' => 'utf8',
                ],
                'testing' => [
                    'adapter' => 'mysql',
                    'host' => 'localhost',
                    'name' => 'testing_db',
                    'user' => 'root',
                    'pass' => '',
                    'port' => '3306',
                    'charset' => 'utf8',
                ]
            ],
            'version_order' => 'creation'
        ];

      • Change the line 'migrations' => '%%PHINX_CONFIG_DIR%%/db/migrations', to 'migrations' =>  __DIR__ . '/db/migrations'
      • Also change the line 'seeds' => '%%PHINX_CONFIG_DIR%%/db/seeds' to  'seeds' => __DIR__ . '/db/seeds'
      • In the production, development, and testing element, change the name, user, and pass values to dabatase, user, password that are set in your mySQL database. You can configure different value for each environment, but for this article we just set it the same. 
      • Also create directory db/migrations, and db/seeds in the project directory.
      • The reason to change to __DIR__ is that we are going to base the phinx migrations folder on the root directory of the projects. You can also go with the default, but you will need to set PHINX_CONFIG_DIR in the environment variables, either by setting in the computer environment variables, in the running terminal, or the VSCode settings. 
    1. Next, is to create migration scripts. Run: phinx create [Name of the migration)
      • The phinx create command requires a name, which must be a camelcase and cannot start with a number. 
      • For example we will run :  phinx create FirstScript
      • This will create our first migration script in the  db/migrations folder 
      • The file name prefix with a timestamp and the name are changed to lower case with each word separated by underscore. 
      • The file is a php with the class with the name matching the the command argument, and with a single 'change' method.
      • With this single method, the phinx can figure out the rollback command from this migration, if the migration script in written in the PHINX API syntax. However there are couple limitation of this behaviour:
        • If the the table is created using raw sql query, the rollback will not attempt to figure out the rollback query during rollback operation. 
        • The same if is there is query execution in the script.
      • If you prefer to handle the rollback manually in your migratin script, you can use two methods ('up' and 'down') instead of 'change' method. The 'up' method is run during migrate command, while the 'down' is executed during rollback command.
      • I will give example for two approaches in two migrations, FirstScript and SecondScript
        • FirstScript     
          • public function change(): void
                {
                    $table = $this->table('users');
                    $table->addColumn('username', 'string', ['limit' => 50])
                        ->addColumn('email', 'string', ['limit' => 100])
                        ->addColumn('password', 'string', ['limit' => 255])
                        ->addColumn('created_at', 'datetime', ['default' => 'CURRENT_TIMESTAMP'])
                        ->addColumn('updated_at', 'datetime', ['default' => 'CURRENT_TIMESTAMP', 'update' => 'CURRENT_TIMESTAMP'])
                        ->addIndex(['username'], ['unique' => true])
                        ->addIndex(['email'], ['unique' => true])
                        ->create();
                }
        • SecondScript
          •   public function up(): void
                {
                    $sql = 'CREATE TABLE orders (
                        id INT AUTO_INCREMENT PRIMARY KEY,
                        orderItem VARCHAR(50) NOT NULL,
                        quantity int NOT NULL,
                        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                    )';

                    $this->execute($sql);
                }

                public function down():void
                {
                    $sql = 'DROP TABLE orders';
                    $this->execute($sql);
                }
    2. Next we will run the migration to update the DB with these two migratin scripts.
      • Run: phinx migrate -e development
      • The option -e is for the environment. The environment list is configured in the phinx.php
      • you can check your DB, to make sure it is 
      • Notice that there is a phinxlog table, which track the migration scripts that are run already

    3. We will also create a third migration for report table, run: phinx create ThirdScript
    4. Before we run migrate again, we can check the status, run: phinx status 
      • You can see from the status, the ThirdScript has not been migrated yet and marked as 'down
    5. Run the the migration again: run: phinx migrate -e development
      • Now all scripts has been run, Please check the DB, to make sure all table has been created including the new 'report' table.
      • When you run the status again, all scripts are shown as up. 
    6. You can rollback change by running: phinx rolback
      • Please check 'report' table has gone, and the entry for the third script in the phinxlog is gone. 
      • You can also check the status again, the third script will be shown as 'down' again. 
      • You can rollback more that one, for example two previous scripts,  by running: phinx rollback -t 2
    7. Next,for development, you would normally need some sample operational data. In phinx can put them in the seeder. In phinx configuration, there is an option to specify where you put the seeder folder. The default folder is '/db/seeds'. 
      • In this example, we will create a seeder called User Data, run : phinx seed:create UserData
      • The file UserData.php will be created in seeder folder

      • And the contain of file, and you can execute insertion query there.
      • <?php

        declare(strict_types=1);

        use Phinx\Seed\AbstractSeed;

        class UserData extends AbstractSeed
        {    
            public function run(): void
            {
        $table = $this->table('users');

                // inserting only one row
                $singleRow = [
                    'username'    => 'bb',
                    'email'  => 'bb@yahoo.com',
                    'password'  => 'bb'
                ];

                $table->insert($singleRow)->saveData();
            }
        }
      • You can execute the seeder by running: phinx seed:run
      • Note:
        • Seeder scripts are not track, 
        • when running the seeder scripts, all scripts in the seeders folder will be executed. 
        • If you want to run just a particularly seeder script, e.g UserData script, you can run: phinx seed:run -s UserData
    8. The last thing is to integration the migration into the application. We want everytime the application run it make sure it apples the migration script. There are pro and cons to apply the migration directly in production. Some prefer to apply the migration changes during CD/CI pipelines, and some others prefer to apply manually in the production to safeguard any potentially failure. In this article we will see how to integrate directly in the application. Note we don't normally integrate seeder in the application, as seeder intended for development only.
      • To integrate directly, you need to insert the migration command in the application bootstrap, which run every application start. The migration will need Phinx autoloader and Phinx configuration file, and below example is a bootstrap.php located in the root  of the project
      • <?php
            require_once __DIR__ . '/vendor/autoload.php'; // Path to Phinx autoloader

            // Determine the environment based on server variables (e.g., domain name)
            if ($_SERVER['SERVER_NAME'] === 'localhost') {
                $desiredEnvironment = 'development'; // Development environment
            } else {
                $desiredEnvironment = 'production'; // Production environment
            }

            // ... [Further logic remains the same as previous examples]

            // Run Phinx migrations for the determined environment
            $phinxCommand = __DIR__ . "/vendor/bin/phinx migrate -e $desiredEnvironment";

            // Capture output using `exec()`
            $output = [];
            exec($phinxCommand, $output, $returnCode);

            // Check if the command executed successfully
            if ($returnCode === 0) {
                // Output captured lines (for example, print them)
                foreach ($output as $line) {
                    echo $line . PHP_EOL;
                }
            } else {
                // Handle error if the command fails
                echo "Error occurred while running Phinx migrations." . PHP_EOL;
            }
        ?>
      • To check if this working, delete the tables in the DB 
      • Then, run the bootsrap.php: php bootstrap.php
      • Check the status: phinx status
      • Lastly check the DB, make sure all tables are created. 

    Note: 
    • The migration is important tool to share the database changes between developers working on the same project. It is also important aspect when push the DB changes from the development to the production. We have not touch on the topic fully of the migration to production or CD/CI pipeline yet. 
    • Phynx come with webbrowser interface, where you can see the status, migrate and rollback. Run the server using:
      • php -S localhost:8000 vendor/robmorgan/phinx/app/web.php
      •  to check the status, then just browser to http://localhost:8000
      • to migrate in the browser address, type: http://localhost:8000/migrate
      • to rollback in the browser address, type: http://localhost:8000/rollback 
    • Documentation to use phynx ca be found here:
      • https://book.cakephp.org/phinx/0/en/index.html

























    Thursday, 7 September 2023

    Tips: Debugging into nuget and microsoft package

    This is quick tip for debugging into nuget package and microsoft package;

    The default behaviour in Visual Studio only show the exception when running in debugging mode.

    • In Visual Studio go to Tools –> Options –> Debugging –> Symbols:


    • Disable ‘Just my Code’ and enable Source Server and Source Link Support in Tools → Options → General



    • And make sure when running the application, make sure Debug → Windows → Exception Settings, is set for Common Language Runtime Exceptions (to trap any exception thrown) 


    Sunday, 9 May 2021

    Blazor framework: What I learned

    1. Introduction

    Hi, there just want to share my experiment with the Blazor framework. I have developed front-end using ASP.NET MVC and React.js before in a commercial capacity. Blazor has been there for a while before I decided to give it a try on my projects at work.

    Sunday, 14 February 2021

    EF Core 5 data migration in .NET 5 : in a separate library and automatic deployment

    I have been thinking to write this topic for some time. I did a project in the past with EF data migration, but things have changed and its library dependencies have changed as well. Now, moving forward to January 2021, I will do this in  .NET 5 project and with EF Core 5 (5.0.3)

    The source code of this project can be accessed from Github.

    Sunday, 7 February 2021

    NHS MIM and DMS tools: Code generation, schema and validation

    1. Introduction

    When working with the NHS projects, I need to deal with a large number of linked schemas, particularly with domains that use the NHS Messaging Implementation Manual or the NHS Domain Messaging Specification. The MIM or DMS is pretty much the same, except MIM covers multiple domains while DMS only covers just one domain. MIM was firstly introduced to cover domains like EPS, Referral (Choice and Book), GP2GP, and PDS. Later one NHS agency chose to publish specification per domain thus DMS was introduced. MIM or DMS contains specification artifacts which are the output from HL7 V3 modelings such as interaction and messaging specification within a domain or multiple domains.

    Saturday, 14 November 2020

    C# Code Generator from Schema

    When you work in the back end, once in a while, you will need to generate code from XML schema. Many applications define their data model using XML schema. Particularly when working with NHS projects and working with the integration with legacy NHS services, which is based on HL7 V3 MIM (Manual Implementation manuals) or DMS (Domain Message Specifications). I need a library in C# to work with the data models. In the past, when I was still working for a primary NHS GP provider, we used a modified version of CodeXS, which is not available anymore publicly. 

    Sunday, 27 October 2019

    Hackathon: Healthcare Interopen

    Here is my week in Interopen hackathon 14 -15 October 2019, and it has been a while ago now. The hackathon is a demonstration of how Healthcare IT Suppliers can interoperate with each other, particularly using FHIR data standards. There were two teams from EmisHealth, and I was represented EmisHealth from GPConnect as a technical lead for this hackathon. Our team focused on Medication Reconciliation workstream. During the course of the two days, I built the API to aggregate Medication data from different suppliers, Orient, Better Health, and Ascribe and they were consumed by the UI developed by our second team, and also consumed within the EMIS Web product.

    Wednesday, 25 September 2019

    NET Core 3.0: SDK, Runtime and Set up for Development

    1. Introduction

    .NET Core 3 was just released recently, along with C# 8, with poweful features and improvements. As I am planning to write a couple of articles about .NET Core and its interactions with different kinds of software packages, this is a good time to do so. This is likely to be the first of many articles about the .NET Core in my blog.

    I will concentrate first on the topic of the .NET Core SDK and Runtime Versioning, and the Set up on a development machine in this article. .NET Core evolution has gradually resulted in many SDK and runtimes and installing the latest SDK and Runtime sometimes is not sufficient in my experience. Without a strong foundation and a good understanding of various things, a little hiccup is likely to throw us into confusion. This article is my attempt to demystify this kind of experience through many trials and errors and hopefully put us in a strong foot to start a .NET Core journey going forward. Potentially there are many things I may have missed along the way, please free to comments and I am happy to rectify after some double-checking.

    Sunday, 15 September 2019

    Working in an agile Team

    When I first joined my current company, as a software developer, I worked in a waterfall engineering process environment. I had a team lead which would give some job to do, and for the rest of the time, I could spend a number of days without interaction with other people. Working in those days was soul-sucking, draining my energy and motivation bit by bit. Things improved a little bit when I was moved to a larger team, and the situations were pretty much still the same, but with harder and complex problems to solve and this gave me a bit more motivation to work.

    FHIR Path Validation with SpecFlow

    I worked on a project related to FHIR (Fast Health Interoperability Resources), and I was temporarily moved to the test automation team to help them with their workload. I learned soon that they wrote a lot of validators code to interrogate and validate different part of FHIR resources. For example there were ObservationValidator, ImmunizationValidator and the list went on.

    I was thinking this was not effective as it did not conform DRY (Don’t Repeat Yourself) principles. I did my research and considering different alternative ways to replace the framework such as using JSON path, XPath and lastly FHIR Path. FHIR Path seems to be no brainer solution to choose from as it is written especially for navigating FHIR resources.

    The full specification of the FHIR Path can be found here . Here is some snippet from the web page explaining what FHIR Path is.

    Friday, 21 December 2018

    End of 2018

    The end of 2018 is on the horizon now. Joining with many other in the world, this is the best time of the year to reflect and make a resolution for the year to come.

    Reflecting my life in 2018

    At the beginning of the year, I was promoted to a Senior Developer role within my company after a successful internal interview process. The process pretty much the same as if you are going to be interviewed by an external company, which comprised of corporate value interview, behavior interview, and technical skills interview.

    The first two interviews were using STAR model (Situation, Task, Activity, Result) approach, while technical skills interview include take-home application development, presentation, and interview. The take-home application was weather API application development. I only have less than one week to prepare, so I focus on the backend side of the application and only a slight touch on the front end. The complete code can be seen in the my gitHub repo here . The overall process going pretty smooth for me.

    This year I also learned how to look after what I eat daily. Diet is important, and become very important after 40-an. Initially, I opt-in for low carbohydrate diet, my gradually add some carbohydrate back to my diet. I end up with DASH diet, which comprises half vegetables and fruit, a quarter of protein and quarter of carbohydrate. I also exercise regularly by running to/from work which takes about 30 minutes one leg of the journey.  Having done it for two months, my blood pressure gradually dropped to the borderline of normal range 120/80.

    During this time, I also realized that a healthy lifestyle is VERY important, I do a lot of research about healthy lifestyle and become more aware of it, and became my first priority during this time. I put a list about healthy food I can consume daily, and I also start to avoid certain food. There are still many things to do on my list to acquire a healthy lifestyle, which  I am going to make a resolution for next year.

    The other thing that happened to me this year was I got my residence permit in the UK in November. So no more visa application to stay and live in the UK, and free to work anywhere if I so wish. I applied at the same time as my wife at the PEO (Premium Service Center) in Liverpool and got approval on the same day. We overjoyed and spent the rest of the day sightseeing in the city.

    At the end of the year, we are getting a family visit from my wife side and we will travel around the UK.

    Friday, 15 December 2017

    Clean Factory Design Pattern with IoC container

    Audience


    This article expects audience have familiarity with Dependency Inversion Principle (DIP) and Factory Design Pattern. For simplicity, the code is not defensive and there is no guarded statements. The code is using Simple Injector, but the described principles applies to other IoC container frameworks as well. The source code of the examples can be found in github by following this link


    Problem


    When implementing a factory class in a project which uses a Inversion of Control (IoC) container, and you arrive to the solution described below, then this article is for you:
    using System;
    using DirtyFactory.Dependencies;
    
    namespace DirtyFactory.Processors
    {
     internal class ProcessorFactory : IProcessorFactory
     {
      private readonly IDependencyOne _depOne;
      private readonly IDependencyTwo _depTwo;
      private readonly IDependencyThree _depThree;
    
      public ProcessorFactory(IDependencyOne depOne, IDependencyTwo depTwo, IDependencyThree depThree)
      {
       _depOne = depOne;
       _depTwo = depTwo;
       _depThree = depThree;
      }
    
      public IProcessor Create(RequestType requestType)
      {
       switch(requestType)
       {
        case RequestType.Internal:
         return new InternalProcessor(_depOne, _depTwo);
        case RequestType.External:
         return new ExternalProcessor(_depOne, _depThree);
        default:
         throw new NotImplementedException();
       }
      }
     }
    }
    

    Monday, 21 August 2017

    Deep Dive into OWIN Katana and Web API


    I was asked to give a presentation about OWIN and Web API to a different development team, as they wanted an introduction to the technology and no one in the team had exposure to that technology before. Prior to that, I have developed a number of internal API for our company. With the presentation slides and materials, I decide to write them down as a blog post as well, so it will be documented properly. I put a lot of extra information compared to the original presentation to cover a broader audience in the internet.

    Saturday, 25 March 2017

    Generic Pattern: How to do Fluent-API on both Derived and Base classes

    I would like to share a lesson learned from work. I am working on a FHIR (Fast Healthcare Interoperability Resources) project. The task at hand was to create builder classes, which basically populate properties of different kinds of resource objects (e.g Patient, Order, Schedule , etc). All these resources are derived from the same object called Resource, which comprises properties such as Id, Meta (contains VersionId and Profile). The derived classes may have their own specialization properties/fields.

    Saturday, 28 January 2017

    SNOMED CT (Systemized Nomenclature of Medicine Clinical Term)

    With recent NHS initiative to replace their clinical terminology, READ Version 3(or CTV3), with SNOMED CT (Systemized Nomenclature of Medicine Clinical Term), there may be a lot of questions raised about this terminology. I first knew about this terminology, in 2008,

    Saturday, 21 May 2016

    Dependency Inversion Principle: Part 5 - Using DIP/IoC container

    (Note: you should read Part4 - Refactoring Using DIP before in order to understand this section)

    I can just stop after refactoring code in previous section. I don't really need to use a DIP/IoC container. However most containers will have some additional features which enable us to tidy up the class composition code. You can even write your own IoC container with the features you really need.