Refactoring 012 - Reify Associative Arrays

Refactoring 012 - Reify Associative Arrays

Leader ●1 ●47 ●113
calendar_today ago β€’ schedule16 min read

Converting your anemic dictionaries is easy

TL;DR: Convert your key/value into full behavioral objects

Problems Addressed πŸ˜”

https://maximilianocontieri.com/code-smell-27-associative-arrays

Context πŸ’¬

You have anemic associative arrays that hold unstructured data.

You want richer objects with stricter controls.

Static typed languages can also add type checking to these objects.

Steps πŸ‘£

  1. Find the references to the object or associative array

  2. Reify it

  3. Replace generic calls with setters and getters for every key.

You can also debug them better this way.

  1. Add parameter and return type hinting to interfaces.

Do this if your language supports it.

  1. Add stronger assertions on the setters between different keys.

(if you are using TCR, you can do baby refactoring steps)

Sample Code πŸ’»

Before 🚨

<?

class AuthenticationHelper extends Singleton {

  private $data = [];

  function setParameter(string $key, ?$value) {
    // no type checking
    // value as the name is too generic
    // Since SOME parameters might be null
    // You can't check a single parameter for not null

    $this->data[$key] = value;
  }

  function getParameter(string $key) {
    // no return type hinting
    return $this->data[$key] ?? null;
  }

}

// Usages

AuthenticationHelper::getInstance
  ->setParameter('oauth2_token', []);
// type error not caught

AuthenticationHelper::getInstance
  ->setParameter('scopes', null);
// We need to enforce this not to be NULL

AuthenticationHelper::getInstance
  ->setParameter('user', 'Elon');
// This should not mutate
// No validation with business rules

$credential =
  AuthenticationHelper::getInstance
    ->getParameter('oauth2token');
// Typo not detected

// You can not easily find
// references to methods setting the oauth2_token

After πŸ‘‰

<?

class AuthenticationCredentials {

  private $user;
  private $oauth2_token;
  
  function __construct(User $user) {
    $this->validateUser($user);
    // Specific validation rules
      
    $this->user = $user;
    // Can't mutate 
  }

  function oauth2_token(string $token): void {
    // You can add specific validations
    $this->oauth2_token = $token;
  }

  function oauth2_token(): string {    
    // Return type hinting
    return $this->oauth2_token;
  }

}

// Usages

$credentials = new AuthenticationCredentials(new User('Elon'));
// Valid since creation
  
$credentials->oauth2_token([]);
// type errors are caught

$credentials->oauth2_token(null);
// can't be null. Fail fast

$credentials->scope();
// Typo detected

Now, you have an anemic data class.

Also known as a DTO.

It is time to give it behavior.

You can also remove some getters and setters.

Type πŸ“

[X] Semi-Automatic

You can perform this refactor with the aid of an IDE.

Safety πŸ›‘οΈ

This is not an automatic refactoring.

Small steps are safe if you have good coverage.

Why is the Code Better? ✨

Your new object fails fast and is more declarative.

You can debug it easily and find the referencing methods.

How Does it Improve the Bijection? πŸ—ΊοΈ

An associative array is a generic container with no real-world meaning.

Its keys are strings that could hold anything, valid or not.

A reified object gives each key a name, a type, and a purpose.

Code should map to the real world, following the Bijection principle.

Every concept in the domain needs a counterpart in the code.

That is the core idea behind the MAPPER.

The new object's name and methods describe what it represents.

Limitations ⚠️

Dynamically typed languages can't enforce type or domain restrictions.

This applies to the values inside the object.

Tags 🏷️

  • Anemic Models

Level πŸ”‹

[X] Beginner

https://maximilianocontieri.com/refactoring-002-extract-method

Refactor with AI πŸ€–

Suggested Prompt: 1. Find the references to the object or associative array.2. Reify it into a full object.3. Replace generic calls with setters and getters for every key.4. Add parameter and return type hinting to interfaces.5. Add stronger assertions between different keys.

Without Proper Instructions With Specific Instructions
ChatGPT ChatGPT
Claude Claude
Perplexity Perplexity
Copilot Copilot
You You
Gemini Gemini
DeepSeek DeepSeek
Meta AI Meta AI
Grok Grok
Qwen Qwen

Conclusion 🏁

Associative arrays are convenient until they grow into hidden domain models.

Once several parts of your code read and write the same keys, reify them.

A dedicated object turns implicit rules into explicit, testable behavior.

You gain type safety, fail-fast validation, and traceable references.

See also πŸ“š

Wikipedia: Reification

https://refactoring.guru/replace-data-value-with-object

Credits πŸ™

Image by MustangJoe from Pixabay


This article is part of the Refactoring Series.

https://coderlegion.com/13921/how-to-improve-your-code-with-easy-refactorings

Part 3 of 3 in Refactorings
πŸ”₯ Join developers growing publicly
Share your knowledge, build in public, and grow your developer presence with a global community.

More Posts

Refactoring 038 - Reify Collection

Maxi Contieri - Feb 5

Refactoring 011 - Replace Comments with Tests

Maxi Contieri - Jun 17

Refactoring 010 - Extract Method Object

Maxi Contieri - Jun 9

Refactoring 009 - Protect Public Attributes

Maxi Contieri - Apr 2

Refactoring 008 - Convert Variables to Constant

Maxi Contieri - Mar 28
chevron_left
6.5k Points β€’ 161 Badges
Buenos Aires, Argentina β€’ maximilianocontieri.com
67Posts
3Comments
4Connections
Learn something new every day
Software Engineer and author of Clean Code Cookbook (https://amzn.to/4... Show more

Related Jobs

View all jobs β†’

Commenters (This Week)

3 comments
2 comments
2 comments

Contribute meaningful comments to climb the leaderboard and earn badges!