Refactoring. RegExp.
Tags: regex, cleancode, refactorit, refactoring
Published: 2022-12-31 10:08:53

Hi! Today we will take a look on the competition between reg exps or.. their non-existence. 

### [Atbash Cipher](https://exercism.org/tracks/typescript/exercises/atbash-cipher)

Let's take a look on a quite interesting, but still simple task - to write [Atbash Cipher](https://en.wikipedia.org/wiki/Atbash)

> _Create an implementation of the atbash cipher, an ancient encryption system created in the Middle East._
> The Atbash cipher is a simple substitution cipher that relies on transposing all the letters in the alphabet such that the resulting alphabet is backwards. The first letter is replaced with the last letter, the second with the second-last, and so on.
> An Atbash cipher for the Latin alphabet would be as follows:
> `Plain:  abcdefghijklmnopqrstuvwxyz`
> `Cipher: zyxwvutsrqponmlkjihgfedcba`

First let's take a look on excellent solution from Bob. 

### Bob's solution 

[Link to solution in Exercism](https://exercism.org/tracks/typescript/exercises/atbash-cipher/solutions/bobahop):

```typescript
export function encode(plainText: string, isDecoding:boolean = false): string {
  let output: number[] = [];
  let count = 0;
  const aAscii = 'a'.charCodeAt(0);
  const zAscii = 'z'.charCodeAt(0);
  let cAscii: number;
  
  for (let c of [...plainText.toLowerCase()]){
    if (c >= 'a' && c <= 'z')
      cAscii = zAscii - (c.charCodeAt(0) - aAscii);
    else if (c >= '0' && c <= '9')
      cAscii = c.charCodeAt(0);
    else
      continue;
    if (count == 5) {
      if (!isDecoding) output.push(32);
      count = 0;
    }
    output.push(cAscii);
    count ++;
  }
  return String.fromCharCode.apply(null, output);
}
export function decode(cipherText: string): string {
  return encode(cipherText, true);
}
```

#### Pros
The code is well structured.

#### Cons

- The method `encode` includes an additional flag as a parameter which looks redundant and make logic more complex.
- All logic at one place. The method can be easily splitted into few smaller.
- Some values can be presented as consts to remove "magic" chars and numbers from the code.
- we can make function more `functional` by replacing `let`s with `const`s and providing `chaining` for greater readability.
- Let's introduce **Reg Exps** to remove redundant logic!

#### Possible refactoring
As we can see - the list of possible changes quite big. But the question is - will it help to the end user? Let's take a look!

### After some changes

After all mentioned above things applied - the new code is looking like that:
```typescript
const PUNCTUATION_AND_SPACE_REGEX = /[\s,.!?]/g;
const GROUP_OF_FIVE_REGEX = /(.{1,5})/g;
const A_CODE = 'a'.charCodeAt(0);
const Z_CODE = 'z'.charCodeAt(0);

const groupText = (text: string) => (text.match(GROUP_OF_FIVE_REGEX) ?? []).join(" ");

const isAlphabeticChar = (code: number) => code >= A_CODE && code <= Z_CODE;

const encodeChar = (char: string) => {
  const charCode = char.charCodeAt(0);
  const newCharCode = isAlphabeticChar(charCode) ? A_CODE + (Z_CODE - charCode) : charCode;
  return String.fromCharCode(newCharCode);
}

const cleanText = (text: string) => text
  .toLowerCase()
  .replaceAll(PUNCTUATION_AND_SPACE_REGEX, "");

const applyCipher = (text: string) => [...cleanText(text)]
  .map(encodeChar)
  .join("")

const encode = (plainText: string): string => groupText(applyCipher(plainText));
const decode = (cipherText: string): string => applyCipher(cipherText);
```

Please, put in comments what solution you prefer more. Also do not hesitate to left links in Exercism for your own solutions - sharing is caring ;)

**Possible improvement**: encapsulate logic inside class. Waitting for your links to solutions in the comments!

Meanwhile you can take a look on the task where I did some useful things [regarding TS types](https://dev.to/dnim/refactoring-ts-types-4hob).