How I made it impossible to write spaghetti code. Part 2
Tags: codequality, php, webdev, beginners
Published: 2024-01-22 18:33:00

> This is the part(3) of a series. I suggest you read parts [1](https://dev.to/denzyldick/the-beginning-of-my-php-static-analyzer-in-rust-5bp8) and [2](https://dev.to/denzyldick/how-i-made-it-impossible-to-write-spaghetti-code-dg4) before this one. 

In part [2](https://dev.to/denzyldick/how-i-made-it-impossible-to-write-spaghetti-code-dg4), I made sure that the test passed correctly. The focus now is how we traverse a block of code inside its scope. We should be able to increase the variables in the formula at the right moment. 

If you have read part [1](https://dev.to/denzyldick/the-beginning-of-my-php-static-analyzer-in-rust-5bp8), you know that we need to implement the validate function that is mandatory in the trait `Rule`. 
```rust

impl Rule for E009 {
    fn validate(
        &self,
        statement: &php_parser_rs::parser::ast::Statement,
    ) -> Vec<crate::project::Suggestion> {

    }
}

```
In part [2](https://dev.to/denzyldick/how-i-made-it-impossible-to-write-spaghetti-code-dg4) we have learned that :
> Nodes are like the conditional statement: if, else, while, for, etc.
Edges are the paths that can be taken. 

The `validate` function will be executed for every statement in a source code. In the source code below, there are 32 lines of code. 

```php
<?php

class Index{

  public function tooComplex(){
    $a = 1;
    $b = 2;


    if($a > $b){
      if($b < $a){

        if($a == $b){

          while($b > $a){

          }

        }
      }
    }
  }
}

```

[Phanalist](https://github.com/denzyldick/phanalist) needs a way to detect when we are in the function's scope with the name `tooComplex().` With pattern matching, it is super easy to detect if the statement is either: `if`,`else`,`etc..` The first statement that I want to match for is `class Index{` and from there, we will continue down the tree. If you think the same way as I do you know that I will be using recursion to calculate the cyclomatic complexity. After we have matched the scope of the `tooComplex()` function.  

```rust
impl Rule for E009 {
    fn validate(
        &self,
        statement: &php_parser_rs::parser::ast::Statement,
    ) -> Vec<crate::project::Suggestion> {
        let mut suggestions = Vec::new();
        let mut graph = Graph { n: 0, e: 0, p: 0 };
        match statement {
            Statement::Class(class) => {
                for member in &class.body.members {
                    match member {
                        ClassMember::ConcreteMethod(concretemethod) => {
                            match concretemethod.body.clone() {
                                MethodBody {
                                    comments: _,
                                    left_brace: _,
                                    statements,
                                    right_brace: _,
                                } => {
                                   /// HERE !!
                                    }
                                }
                            }
                        }
                        _ => {}
                    }
                }
            }
            _ => {}
        }
        suggestions
    }
}

```

If you aren't familiar with pattern matching, it's kind of a switch keyword on steroids. Look for the                                Look for `/// HERE !!` in the above code.

```rust
 MethodBody {
                                    comments: _,
                                    left_brace: _,
                                    statements,
                                    right_brace: _,
                                } => {
                                    /// HERE 1

                                    }
                                }

```
As you can see we have four parameters that we can use. The ones we are looking for are the statements. The type of this parameter is `Vec<Statement>` meaning it can be anything.

Let's use the `Graph` we previously created in part [2](https://dev.to/denzyldick/how-i-made-it-impossible-to-write-spaghetti-code-dg4)

In the source code below, [Phanalist](https://github.com/denzyldick/phanalist) calls a function with `let graph  = calculate _cyclomatic_complexity();` This function will return a struct of the type `Graph`. The first parameter passed is `statements.clone()`. This function uses recursion to traverse down the tree. In part 4 I will explain the recursion we were thinking about. 
```rust

 let graph = calculate_cyclomatic_complexity(
                                        statements.clone(),
                                        &mut graph,
                                    );
 if graph.calculate() > 10 {
suggestions.push(Suggestion::from("This method body is too complex. Make it easier to understand.".to_string(),
                concretemethod.function,
"E009".to_string() ));
}

```

The `Graph` struct has the `calculate` function we previously used to calculate the cyclomatic complexity. My threshold is always ten, so I will be using that.

If the value exceeds ten, I push the `Suggestion` onto the vector. The vector of `Suggestion` is the value returned to the validate function's caller. 

# Recursion 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wj5yh9nh4jtfjnie3ncf.png)

>  In computer science, recursion is a method of solving a computational problem where the solution depends on solutions to smaller instances of the same problem. Recursion solves such recursive problems using functions that call themselves from within their code. [Wikipedia](https://en.wikipedia.org/wiki/Recursion_(computer_science))

# Conclusion

If you are a PHP developer, you know that a developer can make many more mistakes in PHP. In the future, the list of Rules will continue to grow into something more useful.

Thanks for reading!

Contribution is always welcome if you have a mistake you would like to add to [Phanalist](https://github.com/denzyldick/phanalist).