paint-brush
How to Use the Adapter Design Pattern in Vue.jsby@denislapadatovic
4,871 reads
4,871 reads

How to Use the Adapter Design Pattern in Vue.js

by Denis LapadatovicJune 8th, 2022
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

Vue.js developers often rely on using third-party libraries so they don’t need to develop the basic UI components from scratch. Instead of using the third-party code directly in our code, we should create a wrapper and later use the wrapper in order to benefit from the library in our application. The adapter pattern is a software design pattern that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.

Company Mentioned

Mention Thumbnail
featured image - How to Use the Adapter Design Pattern in Vue.js
Denis Lapadatovic HackerNoon profile picture

While working on modern web products one of the requirements is fast delivery. Due to this requirement developers often rely on using the third-party libraries so they don’t need to develop the basic UI components from scratch. But usually while trying to make their Project Managers happy and deliver fast they forget to think about the code maintainability and quality.


In this article, we are gonna discuss how to increase the maintainability and quality of Vue.js applications while using third-party libraries.


Beginning of the Project

Imagine we are developing a Vue.js application that requires a lot of input fields across all the applications. Let us imagine there are 100+ input fields in our application. Since fast delivery is a high-priority requirement we decided to use a third-party library called Element UI.


In order to display the input element on the screen using the Element UI we will need to write this line of code:


<el-input placeholder="Please input" v-model="input"></el-input>


Since we earlier agreed there are 100+ inputs in our app this means there are exactly the same amount of lines of code like the one above in different components in our application. 🤯


Two Years Later

Project Manager:

Good morning. We need to change our UI framework and switch to Vuetify. The deadline is 1 month. Good luck!


Developers:


Project Manager:

What is the problem? 🤔


Developers:

We need to find all Element UI inputs (100+) and replace them. This could lead to a lot of bugs! 😬


Project Manager: Is there anything we can do to make this process smooth the next time? 🥺


Tech Lead: Guys, how about using the Adapter Design Pattern? 🤔


Developers: Could you please explain it a bit more?


Tech Lead: Yes, sure! Read below.



Adapter Design Pattern

According to Wikipedia, this is the definition of the Adapter Design Pattern:


In software engineering, the adapter pattern is a software design pattern (also known as wrapper, an alternative naming shared with the decorator pattern) that allows the interface of an existing class to be used as another interface. It is often used to make existing classes work with others without modifying their source code.


This definition leads us to the conclusion that instead of using the third-party code directly in our code we should create a wrapper and later use the wrapper in order to benefit from the third-party library in our application.


If the third-party library needs to be changed in the future it will be enough just to replace it in our wrapper component and not in other places inside our code. Since we have standardized input and output for that wrapped the way that wrapper is used will not be changed.

How to implement it in Vue.js

We will use the Element UI & Vuetify for our example.


This is what the App.vue file will look like. We imported the adapter component maintained by us. When we decide to switch to a different UI library the App.vue or any other file which uses this adapter will not require updates.


We should not use the third-party component directly. Use only the adapter component.


App.vue

<template>
  <div>
    <input-adapter v-model="value" />
  </div>
</template>

<script>
import { ref } from 'vue'
import InputAdapter from '@/components/InputAdapter'

export default {
  name: 'App',
  components: {
    InputAdapter
  },
  setup () {
    const value = ref('')
    return {
      value
    }
  }
}
</script>


InputAdapter.vue - Element UI

<template>
  <el-input v-model="value" />
</template>

<script>
import { computed } from 'vue'

export default {
  name: 'InputAdapter',
  props: ['modelValue'],
  setup (props, { emit }) {
    const value = computed({
      get () {
        return props.modelValue
      },
      set (newValue) {
        emit('update:modelValue', newValue)
      }
    })
    return {
      value
    }
  }
}
</script>


InputAdapter.vue - Vuetify

<template>
  <v-text-field v-model="value" />
</template>

<script>
import { computed } from 'vue'

export default {
  name: 'InputAdapter',
  props: ['modelValue'],
  setup (props, { emit }) {
    const value = computed({
      get () {
        return props.modelValue
      },
      set (newValue) {
        emit('update:modelValue', newValue)
      }
    })
    return {
      value
    }
  }
}
</script>


What we can notice is that even if we change our UI component library from Element UI to Vuetify the App.vue doesn’t need any update. It will work perfectly fine as long the input and output data are the same as we had in the previous version.


Sometimes the new third-party component requires a different data structure. The right way to handle this situation could be to prepare the data for the third-party component inside the adapter component and not change it in App.vue or other components which are using the adapter component.

Conclusion

The Adapter Design Pattern is definitely a good practice to build your application when using third-party libraries. At the beginning of the project, it could require more time since we need to create wrappers for every UI component that we are using. But at the time we want to change the library it will be done much faster and easier.