Skip to content

Discussion: Structure, Flow, Architecture #16

Closed
@SleeplessByte

Description

@SleeplessByte

Now that we have some tracking on this repository, I'd like your input on going forward.

Current architecture

The initial architecture is mostly matching the ruby-analyzer, which means it's currently using exceptions as control flow. I'm personally not a fan, but for the use-case it works quite well. The interface API is extremely small:

  • approve: instantly mark as approved
  • dissapprove: instantly mark as dissapproved
  • redirect: instantly mark as "need human eyes"
  • comment: add a comment

I think it's also better than a pure functional approach as follows, because the example below quickly becomes as cognitively complex as the exception flow as soon as you need to nest rules, with the added bonus that if you forget a return, everything breaks (but might not actually error the program):

function execute(program) {
  if (!hasNamedExport(program)) {
    return new Output('dissapprove', { comments: [CommentFactory['named-export']] })
  }

  if (anotherCheck(program)) {
    if (!nestedRequiredment(program)) {
      return new Output('dissapprove', { comments: [CommentFactory['nesting']] })
    }
    if (isMinimal(program)) {
      return new Output('approve', { comments: [CommentFactory['tip-remove-nesting']] })
    }
  }

  ...
}

I do like the way the comment system is set up. It will give reasonable types which actually work, as soon as you give it one parameter (doesn't work with 0 parameters, yet). basically this is supposed to make sure the comments work even when they are extracted to the website-copy repo.

Work in progress

I have started extracting functions from the logic. These composable parts should help you write analyzers. They can do things like, but not limited to:

Additionally I've started on functionality where we can output equivalent code but change the output. The reason for this is we might want to give back alternatives using the solution's code without having to search for it (using location parameters, which can be buggy). For example you can fetch the parameter name of a function, and re-use that in the comments.

Preferable alternative?

The csharp-analyzer has a nice approach where:

  • each exercise gets its own ExerciseSolution class which is constructed with the Program;
  • properties of the program are defined on the ExerciseSolution so the "properties" live in one place
  • each exercise gets its own ExerciseAnalyzer` class (same as Ruby, JavaScript, TypeScript)
  • the analyzer has the flow and logic of which properties lead to which commentary.

This would basically be what we currently have, but refactor out solution properties from the logic. This would also remove most if not all "instance variables" from the analyzer (which I think is a win).

What's the gist?

Personally I would like to keep two-fer as is, but try out new patterns when tackling #13 and #14. Your thoughts and ideas are highly appreciated!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions