Skip to content

Commit

Permalink
[1.0.5] Changed: Language Tweaks in Code Smells
Browse files Browse the repository at this point in the history
  • Loading branch information
Luzkan committed Apr 19, 2022
1 parent 86d1294 commit e781555
Show file tree
Hide file tree
Showing 58 changed files with 326 additions and 303 deletions.
14 changes: 7 additions & 7 deletions content/smells/afraid-to-fail.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
slug: "afraid-to-fail"
meta:
last_update_date: 2022-02-17
last_update_date: 2022-04-19
title: "Afraid To Fail"
cover: "/logos/logo-text-2560x1280.png"
known_as:
Expand Down Expand Up @@ -59,25 +59,25 @@ history:

The _Afraid To Fail_ is a Code Smell name inspired by the common fear (at least among students [[1](#sources)]) of failure, which is professionally called _Atychiphobia_ [[48](#sources)] - being scared of failure.

I am referencing it here because the fear of admitting failure (that something went wrong) is a relatable psychological trait, and facing that fear would be for everyone's benefit. It is not a good idea to hope that maybe someone will get away with it. Surely, maybe even more often than not that would be the case, but the more things stack upon that lack of honesty, the harder it will eventually hit if it ever gets discovered.
I am referencing it here because the fear of admitting failure (that something went wrong) is a common, relatable, psychological trait, and facing that fear would benefit everyone. It is not a good idea to hope that maybe someone will get away with it. Undoubtedly, maybe even more often than not, that would be the case, but the more things stack up on that lack of honesty, the harder it will eventually hit if it ever gets discovered.

In programming, this behavior will clutter the code because after a method or function call, additional code is required to check whether some kind of status code is valid, a boolean flag is marked, or the returned value is not `None`. And all of that outside of the method scope.
In programming, this behavior will clutter the code because, after a method or function call, additional code is required to check whether some status code is valid, a boolean flag is marked, or the returned value is not `None`. And all of that is outside of the method scope.

If it is expected that a method might fail, then it should fail, either by throwing an `Exception` or if not - it should return a special case `None`/`Null` type object of the desired class (following the **Null Object Pattern**), not null itself. For example, if an expected object cannot be received or created, and instead of that some status indicator is sent back (which has to be checked after the method is completed), the smells it generates would be [_Afraid to Fail_](./afraid-to-fail.md) as well as [_Teardown Code_](./required-setup-or-teardown-code.md) Code Smell. Instead, following the **Fail Fast Principle**, the code should throw an error instead.
If it is expected that a method might fail, then it should fail, either by throwing an `Exception` or, if not - it should return a special case `None`/`Null` type object of the desired class (following the **Null Object Pattern**), not null itself. For example, if an expected object cannot be received or created, and instead of some status indicator is sent back (which has to be checked after the method is completed), the smells it generates would be [_Afraid to Fail_](./afraid-to-fail.md) as well as [_Teardown Code_](./required-setup-or-teardown-code.md) Code Smell. Instead, following the **Fail Fast Principle**, the code should throw an error.

### Problems:

#### Code Pollution

Requires additional if checks for return status or null checks which is undesirable.
Require additional `if` checks for return status or `null` checks.

#### Coupling

Creating artificial coupling with the method caller.
Creates artificial coupling with the method caller.

#### Fail Fast Violation

In system design, Fail Fast concept is about reporting immediately when any condition is likely to indicate failure.
In system design, the Fail Fast concept is about reporting immediately when any condition is likely to indicate failure.

### Example

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
slug: "alternative-classes-with-different-interfaces"
meta:
last_update_date: 2022-02-17
last_update_date: 2022-04-19
title: "Alternative Classes with Different Interfaces"
cover: "/logos/logo-text-2560x1280.png"
known_as:
Expand Down Expand Up @@ -59,11 +59,11 @@ history:

## Alternative Classes with Different Interfaces

If two classes have the same functionality but different implementations, they should be merged or a superclass should be extracted to limit [Code Duplication](./duplicated-code.md). This smell occurs whenever a class can operate on two alternative classes (for example, take `Zombie` and `Snowman`), but the interface to these alternative classes are different - when it operates with `Zombie` it calls `hug_zombie()` and with `Snowman`, it has to call `hug_snowman()`.
If two classes have the same functionality but different implementations, developers should merge them, or developers should extract a superclass to limit [Code Duplication](./duplicated-code.md). This smell occurs whenever a class can operate on two alternative classes (for example, take `Zombie` and `Snowman`). However, the interface to these alternative classes is different - when it operates with `Zombie`, it calls `hug_zombie()`, and with `Snowman`, it has to call `hug_snowman()`.

### Causation

This may happen due to the oversight that a functionally equivalent class already exists or when two or more developers are working on code to handle a similar situation, but each of them did not know about each others work. Lack of abstract methods that enforce the expected implementation method names.
This may happen due to the oversight that a functionally equivalent class already exists or when two or more developers are working on code to handle a similar situation. However, they did not know about the other's work — lack of abstract methods that enforce the common implementation method names.

### Problems

Expand Down
4 changes: 2 additions & 2 deletions content/smells/base-class-depends-on-subclass.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
slug: "base-class-depends-on-subclass"
meta:
last_update_date: 2022-02-17
last_update_date: 2022-04-19
title: "Base Class depends on Subclass"
cover: "/logos/logo-text-2560x1280.png"
known_as:
Expand Down Expand Up @@ -56,7 +56,7 @@ history:

The rule is that the child classes should be deployable independently from the parent class. That allows us to deploy the system in discrete and independent components.

When one of these subclasses is modified, the base class does not need to be redeployed as well. In this way, the impact of change is much smaller, and so is proportionally the maintenance effort [[1](#sources)]. This smell is closely related to the [Shotgun Surgery](./shotgun-surgery.md) code smell.
When one of these subclasses is modified, the base class does not need to be redeployed as well. In this way, the impact of change is much smaller, proportionally to the maintenance effort [[1](#sources)]. This smell is closely related to the [Shotgun Surgery](./shotgun-surgery.md) code smell.

### Problems

Expand Down
10 changes: 6 additions & 4 deletions content/smells/binary-operator-in-name.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
slug: "binary-operator-in-name"
meta:
last_update_date: 2022-02-16
last_update_date: 2022-04-19
title: "Binary Operator in Name"
cover: "/logos/logo-text-2560x1280.png"
known_as:
Expand Down Expand Up @@ -60,15 +60,15 @@ history:

## Binary Operator in Name

This is straightforward: method or function names that have binary bitwise operators like `AND` and `OR` are obvious candidates for undisguised violators of **Single Responsibility Principle** right out there in the open. If the method name has _`and`_ in its name and then it does two different things, then one might ask why it is not split in half to do these two different things separately? Moreover, if the method name has _`or`_ then it not only does two different things, but additionally and most likely it has a stinky [Flag Argument](./flag-argument.md) which is yet another Code Smell.
This is straightforward: method or function names that have binary bitwise operators like `AND` and `OR` are obvious candidates for undisguised violators of the **Single Responsibility Principle** right out there in the open. If the method name has _`and`_ in its name and then it does two different things, then one might ask why it is not split in half to do these two other things separately? Moreover, if the method name has _`or`_ then it not only does two different things but also, most likely, it has a stinky [Flag Argument](./flag-argument.md) which is yet another Code Smell.

This might happen not only in the method names, even though it is the place to look for in the vast majority of this kind of smell, but also in variables.
This code smell might happen not only in the method names, even though it is the place to look for in the vast majority of this kind of smell, but also in thevariables.

### Problems:

#### Single Responsibility Principle Violation

Names with conjunction words strongly suggested that something is not responsible for just one thing.
Names with conjunction words strongly suggest that something is not responsible for just one thing.

### Example

Expand Down Expand Up @@ -103,3 +103,5 @@ def save():
---

##### Sources

- [Origin] - Marcel Jerzyk, _"Code Smells: A Comprehensive Online Catalog and Taxonomy"_ (2022)
4 changes: 2 additions & 2 deletions content/smells/boolean-blindness.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
slug: "boolean-blindness"
meta:
last_update_date: 2022-02-16
last_update_date: 2022-04-19
title: "Boolean Blindness"
cover: "/logos/logo-text-2560x1280.png"
known_as:
Expand Down Expand Up @@ -59,7 +59,7 @@ history:

## Boolean Blindness

In the Haskell community, there is a well-(un)known question about the filter function - does the filter predicate means to `TAKE` or to `DROP` (check [example](#example))? Boolean Blindness smell occurs in a situation in which a function or method that operates on `bool`-s destroys the information about what _boolean_ represents. In those situations, it would be much better to have an expressive equivalent of type _boolean_ } with appropriate names. For the filter function, it could be of type `Keep` defined as data `Keep = Drop | Take`.
In the Haskell community, there is a well-(un)known question about the filter function - does the filter predicate means to `TAKE` or to `DROP` (check [example](#example))? Boolean Blindness smell occurs in a situation in which a function or method that operates on `bool`-s destroys the information about what _boolean_ represents. It would be much better to have an expressive equivalent of type _boolean_ with appropriate names in these situations. For the filter function, it could be of type `Keep` defined as `Keep = Drop | Take`.

This smell is in the same family as [Uncommunicative Names](./uncommunicative-name.md) and [Magic Numbers](./magic-number.md).

Expand Down
12 changes: 6 additions & 6 deletions content/smells/callback-hell.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
slug: "callback-hell"
meta:
last_update_date: 2022-02-16
last_update_date: 2022-04-19
title: "Callback Hell"
cover: "/logos/logo-text-2560x1280.png"
known_as:
Expand Down Expand Up @@ -54,21 +54,21 @@ history:

## Callback Hell

Smell with scent similar to the [Conditional Complexity](./conditional-complexity.md) where tabs are intended deep and the curly closing brackets can cascade like a Niagara waterfall.
Smell with a scent similar to the [Conditional Complexity](./conditional-complexity.md), where tabs are intended deep, and the curly closing brackets can cascade like a Niagara waterfall.

Callback is a function that is passed into another function as an argument that is meant to be executed later on. One of the most popular callbacks could be the `addEventListener` in JavaScript.
The callback is a function that is passed into another function as an argument that is meant to be executed later. One of the most popular callbacks could be the `addEventListener` in JavaScript.

Alone in separation, they are not causing or indicating any problems. Rather, the long list of callbacks that are chained together is something to watch out for. This could be called more professionally as a _Hierarchy of Callbacks_ but _(fortunately)_, it already received a more interesting and recognizable name. There are plenty of solutions to this problem, namely: `Promises`, `async` functions, or splitting the big function into separate methods.
Alone in separation, they are not causing or indicating any problems. Instead, the long list of chained callbacks is something to watch out for. More professionally, this could be called a _Hierarchy of Callbacks_ but _(fortunately)_, it has already received a more exciting and recognizable name. There are many solutions to this problem: `Promises`, `async` functions, or splitting the significant function into separate methods.

### Problems:

#### Comprehensibility

Long and deep nested methods are difficult to read and maintain.
Long and deep nested methods are challenging to read and maintain.

#### Inversion of Control Violation

One shouldn't give up the control of how things are used.
One shouldn't give up control of how things are used.

### Example

Expand Down
Loading

0 comments on commit e781555

Please sign in to comment.