Categories
Vuetify

Vuetify — Chips and Inputs

Vuetify is a popular UI framework for Vue apps.

In this article, we’ll look at how to work with the Vuetify framework.

Closable Chips

We can create a closable chop with the v-model directive.

For example, we can write:

<template>
  <v-container>
    <v-row>
      <v-col col="12">
        <v-chip
          v-if="chip"
          class="ma-2"
          close
          color="green"
          outlined
          @click:close="chip = false"
        >Success</v-chip>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({
    chip: true,
  }),
};
</script>

We listen to the click:close event with to set chip to false .

The v-if directive controls whether the chip is displayed.

Action Chips

We can have chips that do something when we click it.

For instance, we can write:

<template>
  <v-container>
    <v-row>
      <v-col col="12">
        <v-chip @click="blinds">
          <v-icon left>mdi-blinds</v-icon>Close blinds
        </v-chip>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({}),
  methods: {
    blinds() {
      alert("Toggling Blinds");
    },
  },
};
</script>

We listen to the click event by setting the click handler top the blinds method.

Then we run the method when we click it.

Chips In Selects

We can use chips in a select element to display selected data.

For instance, we can write:

<template>
  <v-container>
    <v-row>
      <v-col col="12">
        <v-combobox
          v-model="chips"
          :items="items"
          chips
          clearable
          label="Your favorite hobbies"
          multiple
          solo
        >
          <template v-slot:selection="{ attrs, item, select, selected }">
            <v-chip
              v-bind="attrs"
              :input-value="selected"
              close
              @click="select"
              @click:close="remove(item)"
            >{{ item }}</v-chip>
          </template>
        </v-combobox>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({
    chips: ["eat", "drink", "sleep"],
    items: ["walk", "read"],
  }),
  methods: {
    remove(item) {
      this.chips.splice(this.chips.indexOf(item), 1);
      this.chips = [...this.chips];
    },
  },
};
</script>

We listen to the click event to run the select method provided by the selection slot of the v-combobox component.

v-combobox is the dropdown component.

Also, we listen to the click:close event to remove an item when we click on the ‘x’ on the chip.

Custom Lists

We can use chips in a custom list.

To do that, we can write:

<template>
  <v-container>
    <v-row>
      <v-col col="12">
        <v-card class="mx-auto" max-width="500">
          <v-container class="py-0">
            <v-row align="center" justify="start">
              <v-col v-for="(selection, i) in selections" :key="selection.text" class="shrink">
                <v-chip :disabled="loading" close @click:close="selected.splice(i, 1)">
                  <v-icon left v-text="selection.icon"></v-icon>
                  {{ selection.text }}
                </v-chip>
              </v-col>

              <v-col v-if="!allSelected" cols="12">
                <v-text-field
                  ref="search"
                  v-model="search"
                  full-width
                  hide-details
                  label="Search"
                  single-line
                ></v-text-field>
              </v-col>
            </v-row>
          </v-container>

          <v-divider v-if="!allSelected"></v-divider>

          <v-list>
            <template v-for="item in categories">
              <v-list-item
                v-if="!selected.includes(item)"
                :key="item.text"
                :disabled="loading"
                @click="selected.push(item)"
              >
                <v-list-item-avatar>
                  <v-icon :disabled="loading" v-text="item.icon"></v-icon>
                </v-list-item-avatar>
                <v-list-item-title v-text="item.text"></v-list-item-title>
              </v-list-item>
            </template>
          </v-list>

          <v-divider></v-divider>

          <v-card-actions>
            <v-spacer></v-spacer>
            <v-btn
              :disabled="!selected.length"
              :loading="loading"
              color="purple"
              text
              @click="next"
            >Next</v-btn>
          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
export default {
  name: "HelloWorld",
  data: () => ({
    items: [
      {
        text: "nature",
        icon: "mdi-nature",
      },
      {
        text: "wine",
        icon: "mdi-glass-wine",
      },
      {
        text: "calendar",
        icon: "mdi-calendar-range",
      },
    ],
    loading: false,
    search: "",
    selected: [],
  }),

  computed: {
    allSelected() {
      return this.selected.length === this.items.length;
    },
    categories() {
      const search = this.search.toLowerCase();

      if (!search) return this.items;

      return this.items.filter((item) => {
        const text = item.text.toLowerCase();

        return text.indexOf(search) > -1;
      });
    },
    selections() {
      const selections = [];

      for (const selection of this.selected) {
        selections.push(selection);
      }

      return selections;
    },
  },

  watch: {
    selected() {
      this.search = "";
    },
  },

  methods: {
    next() {
      this.loading = true;

      setTimeout(() => {
        this.search = "";
        this.selected = [];
        this.loading = false;
      }, 2000);
    },
  },
};
</script>

We put the v-chip component within the v-col to lay them out when we select items from the v-text-field .

The v-text-field lets us enter some text and the v-list below it will show the items that match what we type.

The categories is a computed property to return the matches.

Conclusion

We can add chips to do different things.

They can also be in dropdowns.

Categories
JavaScript Best Practices

More Bad Smells in Code

Writing software is hard. There’re only a few ways to do it right and there’re many ways to do it wrong and make our lives hard.

In this article, we’ll look at some ways to write bad code by looking at a few codes smells.

Primitive Obsession

Programming languages like JavaScript have 2 kinds of data. They’re primitive values and reference values.

Primitive values are the building blocks of our program. They store things like numbers and strings.

Reference types come in the form of objects. They store multiple primitive values and other objects all under one umbrella.

Objects ultimately have primitive values at the bottom of the object’s tree structure.

If we have a bunch of primitive values that are always together, then we can have an object to put them all in one package.

This way, we don’t have to deal with so many primitive values everywhere.

Switch Statements

Switch statements are conditional statements tat contains many cases indie them.

The problem is that there’re lots of duplication in switch statements.

If we have them scattered in different places, then we’ve to update our different switch statements so that we can change our code.

In this case, we should consider polymorphism instead of using switch statements.

Parallel Inheritance Hierarchies

This occurs when an inheritance tree depends on another tree by composition.

They maintain a relationship where one subclass of a dependent inheritance tree depends on a subclass of another inheritance tree.

This isn’t good since if we have to make a subclass of a class, then we’ve to make a subclass of another.

Therefore, we’re forced to duplicate the inheritance hierarchies when making the 2 classes.

We can eliminate this by moving the instance of one hierarchy refers to the instance of another rather than duplicating the inheritance tree for both classes.

Lazy Class

A lazy class is where we create a class that doesn’t have much in it.

In this case, we should remove it since it cost time and money to maintain an extra class.

Speculative Generality

If we don’t need anything now, then we shouldn’t add it.

Writing flexible code makes our code more complex and that will slow us down.

We should only add code that we need now and make it easy to change later.,

Therefore, we shouldn’t overengineer anything. If we have extra code that isn’t doing much now, then we should remove them.

We can spot them when those pieces of code are referenced by test cases. Then we know that they don’t provide us with much value.

Temporary Field

Temporary fields are ones that are only set in certain cases.

This makes the code hard to understand because we expected an object to need all of its variables.

If we need them, then we can extract them to their own class, so we only reference them when we need them.

Message Chains

Sending a chain of messages around our system isn’t great. We have a message having when something asks for an object and that object asks for another object and so on.

We may be calling a chain of getters or referencing a chain of variables.

In either case, the code is too coupled together with the implementation.

And it’s hard to navigate through the message chain for us to understand the code easily.

We should combine the chain into one so that we don’t have to so many objects.

Middle Man

Encapsulation is important. Therefore, we don’t want all our classes to know the details of another class.

However, we may go too far by introducing a middle man class that is only used to delegate calls to another class.

In this case, we can eliminate the middle man class and just call the code we need directly.

Inappropriate Intimacy

Classes can become too intimate and they know too many details of another class.

This isn’t good because too much knowledge means tight coupling. This means that when we change things in one class, we’ll likely break the code in the other class.

We should break them by removing the intimate code. Put any common code into their own class.

And we should avoid referencing any code that has the implementation details.

Subclasses may also know more than the parent class wants them to know. Un this case, we can hide those details by making them private.

Conclusion

We shouldn’t be obsessed with using primitive values. Use objects to group them when necessary.

Also, classes shouldn’t have too much knowledge of each other. We need encapsulation to losses coupling.

Parallel inheritance hierarchies are bad since they duplicate the inheritance tree.

Categories
JavaScript Best Practices

Bad Smells in Code

Writing software is hard. There’re only a few ways to do it right and there’re many ways to do it wrong and make our lives hard.

In this article, we’ll look at some ways to write bad code by looking at a few codes smells.

Duplicated Code

Duplicated code is almost always bad. If we see the same code structure in multiple places, then we’ve to change it by unifying them and then referencing that piece of code.

For instance, if we have 2 expressions in 2 methods of the same class, then we can put the duplicate expressions in their own method.

When we have 2 expressions in 2 sibling subclasses, then we can put the duplicated expressions in the superclass.

If we have duplicated code in 2 unrelated classes, then we can put them into their own class or top-level function if the language allows us to write standalone functions.

Long Method

We can divide a long method into smaller methods that do one thing.

This way, we can read each method much more easily and know what they’re doing.

The longer a procedure, the harder it is for us to understand. Therefore, we should decompose them into smaller methods that are a few lines long.

We can also clean up our code by replacing long expressions with shorter ones.

For instance, we can replace JavaScript loops with array methods that do the same thing.

Large Class

A large class is trying to do too much. It may have lots of instance variables and methods.

Therefore, we should reduce them by splitting one big class into smaller classes that do the same thing.

We can extract the big class into smaller classes that do one thing only.

This way, we keep things easier to read and understand.

If we’re writing web apps, then we need to separate presentation logic from the business logic, for example.

Then we have 2 pieces of code that do their own thing. We also have to keep them loosely coupled by not referencing too much of each other’s implementation.

Long Parameter List

Long lists of parameters in functions need to be reduced. If we have more than 5, then we’ve to find ways to reduce them.

The fewer parameters we have, the better the function is.

More parameters mean it’s easier to make mistakes when passing them in,

One way to do that is to put everything in an object, then we don’t have to pass different things in as separate parameters.

Divergent Change

If we have multiple classes that change in different ways but share the same code, we can move the common code between them to one location and then reference them there.

This way, only the code that’s different is are in their own place and the common code stays in one place.

Shotgun Surgery

Shotgun surgery is changing different code in different classes. They’re then all hard to find and it’s easy to miss an important change.

We can deal with this by moving the shared code to their own location and we can make the change to that part all at once so that we don’t have to make small changes everywhere.

Feature Envy

This is a code smell where we get all data from many different places and put them together to get some results.

This makes coupling between classes tight and makes any changes risky because of that.

Instead of referencing many parts of our code, we should instead reduce the coupling by creating a method to reference all that code in the originating class and then use that method to get the result that we want.

The data is usually all in one class, but we just didn’t both to access them in a loosely coupled way.

Data Clumps

We may often see the same few pieces of data together in many different places.

If the clumps of data appear as fields, then we can turn those clumps of data into its own object so that we can just reference them anywhere.

If the clumps of data are passed in as arguments to functions, then we can combine them to an object parameter to avoid passing them in as multiple arguments.

Instead, we have one object argument that we can use anywhere/

Conclusion

As we can see, there’re many ways to write code in messy ways.

Duplicate code should be combined. Multiple clumps of data should be combined into one so that we can use them together.

Tightly coupled should be mostly decoupled to reduce risks of breaking things.

Categories
JavaScript Best Practices

Bad Smells in JavaScript Code

Writing software is hard. There’re only a few ways to do it right and there’re many ways to do it wrong and make our lives hard.

In this article, we’ll look at some ways to write bad code by looking at a few codes smells.

Alternative Classes with Different Interfaces

2 classes that do the same thing but with different interfaces aren’t good because of duplication.

We don’t want to have that. Therefore, we may want to create a superclass with the shared code and then have subclasses that have differing methods.

Incomplete Library Class

Reuse isn’t overrated.

Library builders have a tough job. They may make incomplete classes but they don’t let us modify them to do what we want them to do.

Therefore, this makes the library class useless to us unless we can add the functionality that we want.

We may have to add new methods to these classes directly to solve this problem.

For instance, if we have a class that we imported, we can add own methods to it by writing:

const mixin = {
  foo() {
    //...
  },
  bar() {
    //...
  }
}
`
Object.assign(Foo.prototype, mixin);

In the code above, we merged the code from the Foo class’s prototype with the methods from the mixin object to incorporate more methods into the class with the Object.assign method.

Data Class

Data classes are classes that only have fields.

These are classes that are probably manipulated in too much detail by other classes.

Therefore, we should encapsulate the public fields if they’re all exposed as public.

We can also encapsulate collection fields if necessary.

To encapsulate them, we can make the fields private and add methods to access and set them.

Refused Bequest

Subclasses inherit methods that parent classes give access to them.

If we don’t need those classes in the parent, then we can just push them down to the subclasses.

Then not all the subclasses will inherit the methods from the parent class while they can still stay in the subclasses that need to have them.

Comments

Comments are good for some things. We can comment on why we’re doing something, but we don’t need to explain how we’re doing something in the comments since we’re already doing it in the code.

Also commented code is bad. We should take them our since they aren’t run, to begin with.

Conditionals That Aren’t in Their Own Line

We should break conditionals into their own line so that we can read them easier.

So instead of writing:

if (foo) {
  //...
} if (bar) {
  //...
}

We write:

if (foo) {
  //...
}
if (bar) {
  //...
}

Annotate Optional Parameters

Optional parameters should have a default value in JavaScript. For instance, we can write the following code to indicate that a parameter is optional:

const foo = (a = 1) => {
  //...
}

Watch out for “Dead Stores”

Dead stores are when we assign a value to a variable but it’s reassigned without using the original value.

Therefore, we never actually need the original value, so we can remove that line.

So instead of writing:

let x = 1;
x = 8 * 10;

We write:

let x = 8 * 10;

Don’t Invert Our Booleans

Double negatives are always harder to read than direct conditional expressions.

Therefore, we should write in a more direct way is possible. For instance instead of writing:

if (!(x > 10)) {
  //...
}

We write:

if (x <= 10) {
  //...
}

As we can see, the second if statement is much easier to read than the first and it’s also shorter. And they’re both the same.

Use Templates Strings

Template strings are the best kind of JavaScript strings. We can interpolate expressions in it, which we can’t do with any other kind of strings.

Also, we can create multiline strings with it by just typing in the line breaks inside this string.

Since backticks are used as delimiters for template strings, quotations can be used inside strings without escaping them.

Conclusion

Template strings are great. They let us do many more things that we can’t do with old-style strings.

To add more methods to incomplete library classes, we can use Object.assign to add our own methods to them.

Also, we need to encapsulate data classes so that our code isn’t too tightly coupled with data classes.

Categories
JavaScript Best Practices

JavaScript Clean Code — Smells and Heuristics

Bad code has lots of unique characteristics. In this article, we’ll look at each one and what they are. We look at writing comments, functions, and general code smells and heuristics.

Comments

Inappropriate Information

Information that shouldn’t be in the comments like author and changelogs are in the comments. They should be in source control systems, bug trackers, and other record-keeping systems.

Change histories should be in source control systems for example. It has metadata for authors, code changes, change date, etc. These shouldn’t be in the comments.

Comments should be for technical notes about the code.

Obsolete Comment

Comments that are old, irrelevant, or wrong are misleading. They get old quickly. The code should be clean enough to not need so many comments.

They become outdated quickly, so they should be avoided.

Redundant Comment

If the code adequately explains itself, then we don’t need comments explaining it. JSDoc that says nothing more than the signature isn’t also very useful.

They should say things that can’t be shown by the code.

Poorly Written Comments

Comments that are worth writing should be written well. We should make sure that they’re the best comments that we can write.

Commented-Out Code

Commented out code can be misleading. Why are they still there if they’re commented out?

We should delete the code if they aren’t needed. They can also be reverted from the source control system’s change record.

Environment

Build Requiring More Than One Step

Builds shouldn’t require more than one step. The more things we have to do manually, the worse that everyone suffers.

We shouldn’t have to do manual operations like checking code out from source control or run a bunch of commands and scripts every time we have to run a build.

There’re so many build pipeline solutions that the button should be a one-click process.

Tests Requiring More Than One Step

Running tests should also be easy. All tests should be run with one command. Either we can run commands with one click on an IDE or by typing in one command.

Functions

Too Many Arguments

Functions should have a few arguments as possible. No arguments are best. More than 3 is questionable.

Output Arguments

We shouldn’t be returning arguments straight at the end of the function as-is. It just makes no sense.

Flag Arguments

Flag arguments mean that a function does more than one thing, so they should be eliminated.

Dead Function

Functions that aren’t called should be removed. Dead code takes up space and misleads people. We can always get it back from source control history.

General

Multiple Languages in One Source File

One file should only be one language. The more language is in a file, the more confusing it is.

Clean separation of logic and markup is always good. JSX is just a different syntax for JavaScript, so it’s actually one language.

Obvious Behavior That’s Unimplemented

Obvious behavior should be implemented. If it’s so useless that it can stay unimplemented, then we can probably eliminate it.

We should implement obvious functionality as described by a function so that the name isn’t misleading.

Incorrect Behavior at the Boundaries

Developers often trust their intuition when they write their functions and think that everything works. We often ignore corner and boundary cases.

We should check our code by writing tests for these conditions and don’t assume that it’ll work properly with them.

Overriding Safety Mechanism

Safety mechanisms in our code shouldn’t be overridden when we write code. Risky changes should be minimized. The end might be lots of bugs and lots of debugging.

Turning off failing tests are bad and we should think about the possible consequences when we do.

Duplication

Code duplication is bad. Every time we have to change duplicate code, we have to change them in multiple places.

We can remove them by abstracting the code and putting them in a central location.

Coding becomes faster and less error-prone since we only have to change things in one place.

The most obvious form is clumps of identical code.

Another form is conditional statements that appear multiple times in different parts of the code. We can replace them with polymorphic code.

Most design patterns are well-known ways to eliminate duplication. They’re structured to eliminate them.

Code at Wrong Level of Abstraction

When we abstract code, we should make them completely. The separation is complete. All the higher-level concepts to be in the base class.

Constants, variables, and utility functions shouldn’t be in the base class.

Source files, components, and modules should at a higher level of abstraction also be separated from ones with lower levels of abstraction.

We don’t wrong higher-level and lower-level code mixed together.

For example, if we have an Account class:

class Account {  
  saveAccountToDb() {}  
  getAccount() {}  
  setAccount() {}  
}

Then we have code at 2 levels of abstraction because we have saveAccountToDb which is a helper method to save data to the database.

We want to move it to a helper class or function.

Conclusion

Comments should be minimized and are useful and up to date when they’re there.

Functions should have as few arguments as possible and only do one thing. This also means we shouldn’t have flag arguments.

When we write code, we should check for boundary and corner cases to avoid bugs. Also, we should override safety features like removing important tests. They’re probably there for a reason.

Finally, code duplication is bad.