Mir

Merge lp://staging/~alan-griffiths/mir/surface-states-simplification into lp://staging/~mir-team/mir/trunk

Proposed by Alan Griffiths
Status: Merged
Approved by: Robert Ancell
Approved revision: no longer in the source branch.
Merged at revision: 636
Proposed branch: lp://staging/~alan-griffiths/mir/surface-states-simplification
Merge into: lp://staging/~mir-team/mir/trunk
Prerequisite: lp://staging/~vanvugt/mir/surface-states
Diff against target: 1924 lines (+334/-253)
62 files modified
examples/demo-inprocess-egl/inprocess_egl_client.cpp (+1/-1)
include/server/mir/frontend/protobuf_ipc_factory.h (+4/-2)
include/server/mir/frontend/session.h (+0/-3)
include/server/mir/frontend/session_mediator.h (+5/-3)
include/server/mir/frontend/shell.h (+5/-2)
include/server/mir/shell/application_session.h (+11/-5)
include/server/mir/shell/organising_surface_factory.h (+4/-1)
include/server/mir/shell/session_manager.h (+1/-1)
include/server/mir/shell/surface.h (+13/-7)
include/server/mir/shell/surface_factory.h (+9/-1)
include/server/mir/shell/surface_source.h (+4/-1)
include/shared/mir/events/event_sink.h (+6/-5)
include/test/mir_test_doubles/mock_session.h (+0/-2)
include/test/mir_test_doubles/mock_shell.h (+1/-1)
include/test/mir_test_doubles/mock_surface_factory.h (+4/-1)
include/test/mir_test_doubles/stub_ipc_factory.h (+1/-1)
include/test/mir_test_doubles/stub_session.h (+1/-1)
include/test/mir_test_doubles/stub_shell.h (+1/-1)
src/client/make_rpc_channel.h (+2/-2)
src/client/make_socket_rpc_channel.cpp (+1/-1)
src/client/mir_basic_rpc_channel.cpp (+1/-3)
src/client/mir_basic_rpc_channel.h (+6/-0)
src/client/mir_client_library.cpp (+9/-13)
src/client/mir_connection.cpp (+2/-1)
src/client/mir_connection.h (+5/-4)
src/client/mir_socket_rpc_channel.cpp (+32/-33)
src/client/mir_socket_rpc_channel.h (+4/-4)
src/server/CMakeLists.txt (+0/-1)
src/server/default_server_configuration.cpp (+2/-1)
src/server/frontend/CMakeLists.txt (+1/-0)
src/server/frontend/event_pipe.cpp (+6/-7)
src/server/frontend/event_pipe.h (+12/-10)
src/server/frontend/protobuf_message_processor.cpp (+3/-1)
src/server/frontend/protobuf_message_processor.h (+2/-2)
src/server/frontend/protobuf_socket_communicator.cpp (+4/-5)
src/server/frontend/session_mediator.cpp (+2/-3)
src/server/shell/application_session.cpp (+14/-12)
src/server/shell/organising_surface_factory.cpp (+5/-2)
src/server/shell/session_manager.cpp (+4/-2)
src/server/shell/surface.cpp (+19/-12)
src/server/shell/surface_source.cpp (+7/-2)
src/shared/protobuf/mir_protobuf_wire.proto (+3/-1)
tests/acceptance-tests/test_focus_management_api.cpp (+4/-4)
tests/behavior-tests/session_management_context.cpp (+8/-4)
tests/integration-tests/cucumber/test_session_management_context.cpp (+3/-3)
tests/integration-tests/shell/test_session_manager.cpp (+8/-7)
tests/unit-tests/CMakeLists.txt (+0/-1)
tests/unit-tests/client/test_client_mir_surface.cpp (+1/-1)
tests/unit-tests/client/test_mir_connection.cpp (+3/-1)
tests/unit-tests/event/CMakeLists.txt (+0/-5)
tests/unit-tests/frontend/CMakeLists.txt (+1/-0)
tests/unit-tests/frontend/test_event_pipe.cpp (+14/-11)
tests/unit-tests/frontend/test_session_mediator.cpp (+9/-5)
tests/unit-tests/frontend/test_session_mediator_android.cpp (+9/-3)
tests/unit-tests/frontend/test_session_mediator_gbm.cpp (+9/-3)
tests/unit-tests/shell/test_application_session.cpp (+10/-9)
tests/unit-tests/shell/test_organising_surface_factory.cpp (+6/-5)
tests/unit-tests/shell/test_registration_order_focus_sequence.cpp (+11/-10)
tests/unit-tests/shell/test_session_manager.cpp (+16/-15)
tests/unit-tests/shell/test_single_visibility_focus_mechanism.cpp (+0/-1)
tests/unit-tests/shell/test_surface.cpp (+2/-0)
tests/unit-tests/shell/test_the_session_container_implementation.cpp (+3/-4)
To merge this branch: bzr merge lp://staging/~alan-griffiths/mir/surface-states-simplification
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Chris Halse Rogers Approve
Robert Ancell Approve
Kevin DuBois (community) Approve
Daniel van Vugt Pending
Review via email: mp+160583@code.staging.launchpad.net

This proposal supersedes a proposal from 2013-04-23.

Commit message

frontend, shell, tests: surface-states updated to avoid supplying dependencies through public member functions.

Description of the change

frontend, shell, tests: surface-states updated to avoid supplying dependencies through public member functions.

Where possible, dependencies should be supplied as constructor arguments and held as const members.

(This required updates to a few factory interfaces to supply the dependencies.)

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Firstly, needs fixing:
Text conflict in tests/unit-tests/shell/test_application_session.cpp
1 conflicts encountered.

Secondly, I disagree with the approach. There are no strong "dependencies" here. The information in question is all optional to the class receiving it, so should not be passed in constructors. The classes can function without event sinks or surface IDs. They will work as they already do. Only event emission would not happen. So it's optional relative to those classes, and therefore not something to enforce in the constructor.

Aside from anything else, the degree of coupling introduced here looks very high. It's always better to minimize coupling. You can't call it a simplification if coupling is increased and the diff is "+205/-148".

review: Disapprove
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Also, here's an example use-case for changing the event sink of a surface:

Windows (like the one Flash video uses in a web browser) are implemented using reparenting. If Mir was to support such a thing in future then it would be handy to be able to re-assign a surface to a different session. Hence you'd also need to be able to change a surface's event target (its session).

Revision history for this message
Alexandros Frantzis (afrantzis) wrote : Posted in a previous version of this proposal

> Secondly, I disagree with the approach. There are no strong "dependencies" here.

As mentioned in an older comment [1], they are effectively dependencies because of how Mir uses the class. That is, in all cases in production code we need to set both the id and the sink for our features to work properly.

> If Mir was to support such a thing in future then it would be handy to be able to re-assign
> a surface to a different session

The key words are "if ... in the future ...". If we need this in the future, we are free to change the code to suit our needs. Right now the values are meant to be set only once at creation time, and accepting them in the constructor enforces this restriction (and, as mentioned above, also enforces that we always get a fully working object).

[1] https://code.launchpad.net/~vanvugt/mir/surface-states/+merge/158289/comments/348068

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

There is a difference between a local dependency and a system dependency. On the local scale, the classes do not depend on EventSink to work. So on a local scale, it should not affect the constructor.

A surface can emit events. A surface can have an ID. However those are not required attributes for the surface to be created and work as a surface.

No amount of "modern C++ tradition" supersedes the basic programming ideal of low coupling.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> Firstly, needs fixing:
> Text conflict in tests/unit-tests/shell/test_application_session.cpp
> 1 conflicts encountered.

Resolved.

> Secondly, I disagree with the approach. There are no strong "dependencies"
> here. The information in question is all optional to the class receiving it,
> so should not be passed in constructors. The classes can function without
> event sinks or surface IDs. They will work as they already do. Only event
> emission would not happen. So it's optional relative to those classes, and
> therefore not something to enforce in the constructor.

Arguing that a subset of the functionality works without these attributes is an argument that the subset belongs in a class providing just that subset. While we could factor that subset out, I don't think we need to that now.

> Aside from anything else, the degree of coupling introduced here looks very
> high. It's always better to minimize coupling.

I agree that coupling should be reduced - I disagree that this MP increases coupling. For example, the interface used by frontend should not need Session::set_event_sink().

> You can't call it a
> simplification if coupling is increased and the diff is "+205/-148".

You can't measure coupling (or other attributes of the resulting code) by diff size.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

I have stated my opinions strongly. I disagree with this proposal as it significantly decreases readability and maintainability. Those are the traits of high coupling, and things I would like to avoid.

Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

> > Secondly, I disagree with the approach. There are no strong "dependencies"
> > here. The information in question is all optional to the class receiving it,
> > so should not be passed in constructors. The classes can function without
> > event sinks or surface IDs. They will work as they already do. Only event
> > emission would not happen. So it's optional relative to those classes, and
> > therefore not something to enforce in the constructor.
>
> Arguing that a subset of the functionality works without these attributes is
> an argument that the subset belongs in a class providing just that subset.
> While we could factor that subset out, I don't think we need to that now.

I think we're using the term 'coupling' too broadly to make much progress arguing :) I'll propose re-framing the argument, and then give my 2 cents

I think we can agree on this though:
1) Its better if a function call doesn't have any hidden prerequisites, like "you must call function A before you call function B". This is sort of 'coupling of calling requirements".
2) A class with a lot of constructor parameters has a lot of dependencies and might be trying to do too much. This is sort of 'coupling of object dependencies'

my 2cents...
so we have to find a way to balance.

I think that, with regards to notify_change/set_id, set_id() is a dependency that has to be called before notify_change() is called, so the id may as well be in the constructor. Another possibility (if we really don't want any more construction parameters for Surface) is to have another object with expanded functionality that takes

We've tried to mitigate the problem of #2 by having a lot of mocks and stubs and nulls that are easy to plug in and make the object easy to manipulate in test. Since its easier to read a constructor than it is to trace what the call order is, I'd rather plug in mocks/stubs to the constructor than have to trace a call order to figure out if we've fulfilled our usage requirements.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

You are free to propose and land this directly to lp:mir.

I just don't want code like this landing in a branch with my name on it.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote : Posted in a previous version of this proposal

might be the first time there's been 2 rival reviews going on ;-)

again, seems the biggest point of contention is about 2 phase initialization and what has more or less coupling. maybe a new day will let me rephrase a bit better. :) Seems to me that (for example) in msh::Surface msh::Surface's notify_change function is coupled to having the ID, so whether you put it in the constructor or require a set_ function to be called, both depend on having an id to use notify_change() in a way. I'd rather come down on the side of putting it all dependencies in the constructor, because it allows us to see pretty quickly what a class needs, and gives us an easy-to-read signal about if a class is doing too much and needs to refactor. So, msh::Shell, might just be on the point of needing a refactor. (if its constructor is getting "too bloated" of course)

I know we had a debate similar to this one at an earlier point in the project, I hope we have another one next week :)

Revision history for this message
Chris Halse Rogers (raof) wrote : Posted in a previous version of this proposal

This doesn't immediately *look* like a simplification to me.

My understanding is that this is a simplification for clients of this code - ie: consumers of this class no longer have to check if the EventSink or SurfaceID is set.

My question is then - do consumers of this class need to check if the EventSink or SurfaceID is set currently? It looks like consumers of this class generally won't care - if they configure() a surface which doesn't have an EventSink set then nothing will get the event but everything else will work as expected?

review: Needs Information
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

From a high-level perspective I can see two problems here:

1. It's 1000 lines bigger than my proposal. Even if you agree that's not a simplification, but for other purposes, then I think it's still a bit much to review all in one go.

2. This does not solve the problem of code I disagree with ending up in a commit with my name on it. Because once merged it would just show one commit with both our names as authors.

To keep code reviews smaller and simpler, please propose your changes separately (after) surface-states to lp:mir. I won't agree with them, but I won't block them there either.

review: Needs Resubmitting
Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

Just further to Kevin's comment:

"We've tried to mitigate the problem of #2 by having a lot of mocks and stubs and nulls that are easy to plug in and make the object easy to manipulate in test. Since its easier to read a constructor than it is to trace what the call order is, I'd rather plug in mocks/stubs to the constructor than have to trace a call order to figure out if we've fulfilled our usage requirements."

This is false: "lot of mocks and stubs and nulls that are easy to plug in and make the object easy to manipulate in test". You define "easy" by how much effort it requires for someone like you guys (who have been at it for over a year) to modify the code. I define "easy" by how much effort a newcomer requires (with no prior knowledge of the code).

This is false: "Since its easier to read a constructor than it is to trace what the call order is". Constructors do not explicitly state what they're doing, unlike "set_id" or "set_event_sink". And if you did make a mistake somewhere and dereference a null shared_ptr, then the trace would be a call stack. Automatically generated and easier to read.

Revision history for this message
Daniel van Vugt (vanvugt) wrote : Posted in a previous version of this proposal

If you resubmit and prerequisite the surface-states branch, I will close my eyes and happily Abstain.

review: Needs Resubmitting
Revision history for this message
Alan Griffiths (alan-griffiths) wrote : Posted in a previous version of this proposal

> My question is then - do consumers of this class need to check if the
> EventSink or SurfaceID is set currently? It looks like consumers of this class
> generally won't care - if they configure() a surface which doesn't have an
> EventSink set then nothing will get the event but everything else will work as
> expected?

On this point is that consumers shouldn't even know about them - they shouldn't see these functions in the interface they use (i.e. they don't belong in frontend::Surface). Unnecessarily exposing these functions *is* increasing coupling.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

"So, msh::Shell, might just be on the point of needing a refactor. (if its constructor is getting "too bloated" of course"

I assume that means msh::Surface?

I too have questioned in the past whether some of the attributes currently being added to shell::Surface are best modeled as member variables. (As opposed to say, their being an event filter that has an associative map from surface to event sink.)

This proposal doesn't address this question.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Kevin DuBois (kdub) wrote :

looks good to me, although a good future improvement might be to consolidate ApplicationSession's constructor

review: Approve
Revision history for this message
Robert Ancell (robert-ancell) :
review: Approve
Revision history for this message
Chris Halse Rogers (raof) wrote :

It's still not clear to me that this is a simplification, but there's nothing objectionable in here.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
The diff is not available at this time. You can reload the page or download it.

Subscribers

People subscribed via source and target branches