Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command #21

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open

Command #21

wants to merge 4 commits into from

Conversation

xsdc
Copy link
Owner

@xsdc xsdc commented Nov 18, 2024

No description provided.

Copy link
Collaborator

@ryanbrear ryanbrear left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am stopping reviewing this code because it doesn't make sense.

It's very clear you did not put this code into an editor to check for compiler warnings. I did, and the errors were numerous.

You get 1 out of 10 for the quality of this code.


```swift
protocol ImageCommand {
class CarouselViewModel {
private let images: [String]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would images be private on a view model?
And if images is an array of String, should this be called imagePaths?

private(set) var currentIndex: Int

init(images: [String]) {
self.currentIndex = 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why set currentIndex to 0 in the init when you can set a default value inline?

Comment on lines 63 to 64
func navigateToPreviousItem() {
currentIndex = (currentIndex - 1) % images.count
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code will crash the app if the index is currently at 0. Read up on issues with using Remainder operator with negative numbers.

Comment on lines 67 to 69
func navigateToItem(at index: Int) {
currentIndex = index
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code will crash the app if an invalid index is passed in.

init(carouselViewModel: CarouselViewModel) {
self.carouselViewModel = carouselViewModel

self.tapInvoker = TapInvoker()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can't init TapInvoker this way. Try.

Tap Invoker requires parameters. Same goes for all the other Invokers you init in this class other than TimerInvoker (but that is only because TimerInvoker is set up incorrectly).

Comment on lines 263 to 269
// Output:
// Carousel starting index: 0
// Carousel index: 1
// Carousel index: 0
// Carousel index: 1
// Carousel index: 2
// Carousel index: 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest removing this output, in line with removing the print statements.

Comment on lines 274 to 282
// Output:
// Carousel index updated via timer: 2
// Carousel index updated via timer: 3
// Carousel index updated via timer: 0
// Carousel index updated via timer: 1
// Carousel index updated via timer: 2
// Carousel index updated via timer: 3
// Carousel index updated via timer: 0
// ...
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.

func nextImage() {
currentIndex = (currentIndex + 1) % images.count
init(carouselViewModel: CarouselViewModel) {
self.carouselViewModel = carouselViewModel
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are you assigning the view model to a property on the class if it's only used in the init?

If you pass in the commands already configured, then the view needn't have knowledge of the receiver (the view model). See comment below about you configuring all the commands in the init, instead of passing them to the view already configured.


func simulateTapForNextButton() {
tapInvoker.nextButtonTapped()
print("Carousel index: " + "\(viewModel.currentIndex)")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is NO property on your class called viewModel. So how is this print statement even going to work.

self.tapInvoker = TapInvoker()
self.tapInvoker.navigateToNextCommand = NavigateToNextItemCommand(receiver: carouselViewModel)
self.tapInvoker.navigateToPreviousCommand = NavigateToPreviousItemCommand(receiver: carouselViewModel)
self.tapInvoker.navigateToItemCommand = NavigateToNextItemCommand(receiver: carouselViewModel)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You pass a NavigateToNextItemCommand to tapInvoker.navigateToItemCommand, when you should be passing a NavigateToItemCommand. But doing so doesn't make sense since NavigateToItemCommand takes an Index, and you don't have the index yet!

var images: [String]
var currentIndex: Int
class CarouselView {
let viewModel: CarouselViewModel
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which class needs access to this view model from outside this class?

Also, why set the view model property on the class if it's only needed in the init?

Lastly, by injecting the view model into the view you are essentially injecting the receiver into the invoker, coupling them. The whole point of the Command pattern is to decouple them. In order for the view and view model to be decoupled, the view needs to have zero knowledge of the view mode. You can achieve this my injecting invokers into the view, already initid with their receiver (the view model).

Comment on lines +125 to +142
struct TapInvoker {
let receiver: CarouselViewModel

func rightArrowButtonTapped() {
let navigateToNextCommand = NavigateToNextItemCommand(receiver: receiver)
navigateToNextCommand.execute()
}

func leftArrowButtonTapped() {
let navigateToPreviousCommand = NavigateToPreviousItemCommand(receiver: receiver)
navigateToPreviousCommand.execute()
}

func buttonTappedForIndex(_ index: Int) {
let navigateToItemCommand = NavigateToItemCommand(receiver: receiver, index: index)
navigateToItemCommand.execute()
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All your invokers have the same issue as your view: they are coupled to the receiver. You can fix this by injecting the relevant commands, already inited with a receiver, into your invokers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants