-
-
Notifications
You must be signed in to change notification settings - Fork 53
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
Refactor and reuse code #101
Conversation
I had a cursory look at PR and I would say that the refactor make sense to me but some thoughts come in mind... :-)
Not strictly related but something could be helpful is to move the Docker image code into a dedicated repository (i.e. Thoughts? |
I personally like the idea of moving fyne-cross to become fyne cross and get synchronized release. It will have to be discussed with the rest of the community. Maybe we should create a set of issues toward that goal in fyne-cross and aim for inclusion of fyne-cross in fyne for 2.3. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect that @lucor will have more (if anything) to say about the code. It all looks sensible to me but I don't quite have the same knowledge over the codebase. All my local builds of rymdport also work just as before, hence approved :)
This is a great thing to work towards, however I don't think I would have it as a separate command ( |
Good point, that makes sense to me. We already do a similar thing when building from a macOS with a darwin target |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had a little in depth look at the code and the most of the feedback are related about the naming like: ContainerImage
, AllContainerImage
, AllContainerRunner
.
Anyway all changes are internal
and it works locally using docker as before, so feel free to merge if we need it for #108. I'd not block this with a discussion about naming :) Probably they will be lost during the porting to fyne CLI and in any case we can always address them in to a later stage.
internal/command/container.go
Outdated
) | ||
|
||
type ContainerRunner interface { | ||
NewImageContainer(arch Architecture, OS string, image string) ContainerImage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about having a constructor defined as part of an interface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, that isn't the Go pattern, It is not clear what ContainerRunner
is describing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about it, ContainerRunner
is basically the engine definition (podman, docker, kubernetes).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, so Engine
could work, remove the duplication that's tripping me up?
Could use Create
instead of New
so it's not looking like a constructor?
Also I realise here there is ImageContainer
vs ContainerImage
- which is desired?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think ContainerImage
.
internal/command/container.go
Outdated
Debug(v ...interface{}) | ||
GetDebug() bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about moving these methods into a dedicated interface, like Debugger
?
internal/command/container.go
Outdated
GetArchitecture() Architecture | ||
GetOS() string | ||
GetID() string | ||
GetTarget() string | ||
GetEnv(string) (string, bool) | ||
SetEnv(string, string) | ||
SetMount(string, string) | ||
AppendTag(string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need to add these methods as part of an interface ? Should be they removed in favor of a contract with the AllContainerImage
struct ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds doable. I was thinking I would have to change the behavior of some of them, but actually not at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remember that in Go it is idiomatic to remove Get
prefix for simple getter calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are the Os/Arch part of the API at all? a ContainerImage
is a generic construct that is created by the ContainerRunner
calling some constructor passing in state, so this feels a little circular.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After trying to remove them, it actually is more useful than expected as code use a ContainerImage
to build figure out what command to execute. A ContainerImage
is a representation of an Engine/OS/Architecture capability. I think they are for the moment useful where they are.
@Bluebugs it looks like the
|
Indeed, good catch. I missed that part. Will fix it shortly. |
I have added some thoughts around naming. However I was not able to add suggestions in most places as it is not clear of the intent from model presented. Can you please summarise what each of the new interfaces/structs are supposed to describe in one comment so we can understand the bigger picture @Bluebugs? It is a bit confusing that runners contain images bit images have run methods. |
Sounds like a lot of good suggestion. I can have a pass at it tomorrow and we can iterate on the change after that. |
Small attempt at a diagram, not sure it is super usable: classDiagram
Command<|--Linux
Command<|--Windows
CrossBuilder<|--Linux
CrossBuilder<|--Windows
class Command{
<<Interface>>
+Run() error
}
class CrossBuilder{
<<Interface>>
+Build(ContainerImage)
-setupContainerImage(flags, args) error
}
Command-->ContainerImage:Run() Use
CrossBuilder-->ContainerImage:Build() Use
CrossBuilder-->ContainerEngine:setupContainerImage() Use
ContainerEngine<|--LocalContainerEngine
ContainerImage<|--LocalContainerImage
ContainerEngine<|--KubernetesContainerEngine
ContainerImage<|--KubernetesContainerImage
class ContainerEngine{
<<Interface>>
+createContainerImage(arch Architecture, OS string, image string) containerImage
}
class ContainerImage{
<<Interface>>
+Run(vol volume.Volume, opts options, cmdArgs []string) error
}
ContainerEngine-->ContainerImage:create
|
That is really helpful thanks - thought it is missing the PlatformBuilder which was part of my confusion from earlier. |
Adding classDiagram
Command<|--Linux
Command<|--Windows
platformBuilder<|--Linux
platformBuilder<|--Windows
class Command{
<<Interface>>
+Run() error
}
class CrossBuilder{
<<Interface>>
+platformBuilder
+Run()
-setupContainerImage(flags, args) error
}
class platformBuilder{
<<Interface>>
+Build(ContainerImage)
}
CrossBuilder-->ContainerImage
CrossBuilder-->ContainerEngine:setupContainerImage() Use
CrossBuilder-->platformBuilder:Build() Use
platformBuilder-->ContainerImage
Command<|--CrossBuilder
ContainerEngine<|--LocalContainerEngine
ContainerImage<|--LocalContainerImage
ContainerEngine<|--KubernetesContainerEngine
ContainerImage<|--KubernetesContainerImage
class ContainerEngine{
<<Interface>>
+createContainerImage(arch Architecture, OS string, image string) containerImage
}
class ContainerImage{
<<Interface>>
+Run(vol volume.Volume, opts options, cmdArgs []string) error
}
ContainerEngine-->ContainerImage:create
|
internal/command/container.go
Outdated
@@ -59,6 +58,7 @@ type containerImage interface { | |||
Tags() []string | |||
|
|||
Engine() containerEngine | |||
Debugger() debugger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks more like moved rather than removed. In this new position all containerImages must be debuggable. Is this a desirable definition of an image?
Go loose typing indicates that anything could be debuggable, if it provides the facilities to be debugged, rather than stating which interfaces will have to support debugging...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum, I am not sure that I get what you want correctly. Do you mean, I should always cast all Debugger call on the Engine()? Something like: debug, ok := image.Engine().(Debugger)
and then if the debugger is present do call the debugger function?
Thanks for this, I think I am starting to understand.
This feels messy - combining re-use with inheritance. Why not separate the requirement on I hope these ideas are helpful, It should take out some of the seemingly circular usages. |
It is pretty much this already, except it use a ContainerImage to function which is provided by a ContainerEngine.
I kind of want to avoid touching much of the command part as it will disappear, I believe, once we migrate to cli.App. |
I see - but how does the current cli library require that each platform-specific builder rely on the cross builder? |
The cross builder is the provider of Run() which really shouldn't be duplicated, but due to the Cli library requiring the existence of a Run per platform it has to be somewhere. The solution is to either duplicate code (bad) or reuse by depending on cross builder (better). Best will be when we do not need to link the crossBuilder.Run() with the Cli and can then just drop that from the dependencies. |
After discussing debugger on the call this is closer but I am still stuck on :
isn’t there a third option where they don’t have to depend on one another but the common code is used by both? |
I can not think of a different solution until we use cli.App that would be significantly different from any of the one above. I am convinced that using cli.App will solve this problem and that we won't need anymore that duplicated code, but switching to cli.App introduce massive change in the code base and this PR is already big enough that I do not want to do that here. Still I think that that would likely address your problem completely and be your third option. |
f626acd
to
071d846
Compare
Please don't force push after reviews started, it now needs a complete review again as we can't see the changes any more |
Sorry about that. I made a mistake in merging the wrong branch and I had to force push to undo that change. |
I had a look at the code and am not sure I agree that crossBuilder must exist because of the way the CLI works. Looking at it there are 3 methods, two if which just return the name and description, which is different. The third,
This should be approx the same number of lines as you have, but with a cleaner control dependency graph. |
The build failure is unrelated as far as I know and due to a bug with v2.2 |
Or maybe it's not a bug and this is now using Fyne v2.2.1 tools to compile a Fyne v2.1.4 app - we do ask that folk keep the versions in sync. Probably we didn't see this coming but it is a side/effect of using the generated code to insert metadata. I guess we could improve the tooling to try and detect if |
I have updated the calculator module and kicked the tests so we can see if that was the only error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with how this turned out. I'd like to know that @lucor is too though :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, additionally I won't make this blocker. The refactoring is related to internal packages and we can always iterate later, if needed.
Perhaps we should make the current release, then land it to work on with more time? |
Description:
This is "just" a refactor. As I was working on #98, I realize it would be simpler if there was a bit more potential for reusing code around. I am not sure that all of those change are really idiomatic go and feel like doing a PR that "just" move code around and remove duplicated step will make the next PR easier to move forward.
Checklist:
Where applicable:
There should be no functional change. I have only the ability to test with podman at the moment and will be glad if anyone tried with docker.