What is the correct Object Design/Architecture for the following scenario?

I am developing some custom controls in an Object Oriented language (using Swift/Cocoa but this is a technology agnostic question). In particular, I have a horizontal and vertical set of buttons that behave very similarly except for the fact that one is oriented vertically and the other horizontally.

My question: what is the correct way to structure these two ‘things’ in my project:

Should I have a (abstract) parent class that has common functionality and then two derived concrete classes for the specifics needed for horizontal-ness vs vertical-ness. This feels the most correct but given that the object is composed of other objects you are then going to have proliferated throughout the view hierarchy going downwards.

Alternately, should I design one highly generalised class that has a property for orientation and then a lot of if/switch logic in the code to drive behaviour based on this. This feels like a code-smell.

Just go and create two separate similar but technically unrelated classes and just do a little more repeated typing. Since so many things are driven by the orientation this almost seems simpler than 1 above.

Or is there another alternative?

Other canonical examples where this would arise could be horizontal vs vertical:
– scrollers
– stacking panels

To attempt to clarify on regarding design goals and requirements, I would like the question answered in terms of how Apple Software Architects might have approached the NSScrollView class (or how any large organization might approach similar UI library code with “mirror” horizontal and vertical components).

The answer impacts several related vertical vs horizontal classes that aggregate these buttons into rows and columns respectively as the rows and columns themselves are also very similar save for the vertical vs horizontal orientation.

5

As a note up front, I am not familiar with how the Apple UI components commonly work and I mostly have experience working with Qt. This might influence the applicability of my answer.

I would start with a set of widgets that are orientation-neutral, but that can naturally be used where you expect an orientation-specific widget. For example a button where both dimensions can be set as fixed size or stretching and a grid with multiple rows and columns. These are concrete classes that can be used as-is.

With these orientation-agnostic widgets, a vertical button is just a button with a (relatively small) fixed-size width. And a row is just a grid with only one row.
How to realize this depends mostly on how the UI is typically being built.

  • If the UI is mostly coded by hand, you can create orientation-specific derived classes that do nothing more than set the appropriate defaults of their orientation-agnostic base classes. A VerticalButton class would only have a constructor to set the button’s width as a fixed value.
    This doesn’t prevent someone from changing the width back to being variable, but that would be their own fault.
  • If the UI is mostly generated from a graphical designer, I would look into the possibility of having the designer provide the widgets in multiple tastes (horizontal, vertical and orientation-agnostic) that instantiate each the same class with different settings.
    If that fails, I can always fall back to the first option.

Only if the orientation-specific widget needs behaviour that can’t be provided by the orientation-agnostic variant would I consider making a full-fledged class (with more than a constructor) for the orientation-specific widget.
For example, if the text on a vertical button needs to be rotated, but the regular button class doesn’t support text rotation.

Answering in a very abstract and technology/framework agnostic manner, my thinking is as follows

  • What a GUI control is (ie. volume up, volume down) not equates to how it is positioned in a window (a frame of visual reference).
  • Therefore separate the functionality of laying-out from the controls themselves.
  • Use a factory to create various layout managers for Controls (Control can be a common interface that all controls implements or provides – I suggest use composition – and provides information as required by the layout manager. For example a particular component may have a preferred width or height, similarly layout manager may want to instruct the control/component that it is now in a Horizontal layout thus dimensions are so..etc.)
  • in this case a LayoutFactory.createHorizontalLayoutManager().layout(List controls)

What does this facilitate

  • in the future you just need to modify / add / factories or methods in them to create more layout options.
  • LayoutFactory.createHorizontalLayoutManager().layout(List controls) is a Control (various controls like Button, ScrollBar..etc) agnostic. It just knows how to layout a component/control.
  • The control themselves are agnostic to target device (phone,TV,BillBoards,Laptop..etc)..that information can be incorporated into layout manager (even better, an concrete implementation of a Device interface would take a layout manager and it would know what a horizontal layout means in that particular device and render it accordingly)

two derived concrete classes for the specifics needed for horizontal-ness vs vertical-ness. This feels the most correct

Well, to me this feels mostly wrong. Your button can have a dozen properties or more like the orientation, for example it could be resizable, have a specific color, it could be labeled with an image, text or both, and so on. If you are going to create derivations for each property, even when you restrict yourself to properties which don’t change over the lifetime of the object, you will need an additional derivation for each combined property (for example, a VerticalResizableImageButton, HorizontalResizableImageButton, VerticalResizableTextButton, HorizontalResizableTextButton, each of those also in a non-resizable variant, and so on). Imagine how many different derivations this will mean in the end – each new property will multiply the number of needed derivations by a factor. I don’t think this is feasible.

should I design one highly generalised class that has a property for orientation and then a lot of if/switch logic in the code to drive behaviour

I would try to design one highly generalised class that has a property for the orientation, but as few conditional logic as possible. If the part of the code which depends on the orientation really ends up in many if/else statements, it can probably be encapsulated into one or more strategy objects, which are initialized once in the button constructor. For example, a “DragStrategy” (with derived classes “VerticalButtonDragStrategy” and “HorizontalButtonDragStrategy”) for controlling the drag-resizing.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

What is the correct Object Design/Architecture for the following scenario?

I am developing some custom controls in an Object Oriented language (using Swift/Cocoa but this is a technology agnostic question). In particular, I have a horizontal and vertical set of buttons that behave very similarly except for the fact that one is oriented vertically and the other horizontally.

My question: what is the correct way to structure these two ‘things’ in my project:

Should I have a (abstract) parent class that has common functionality and then two derived concrete classes for the specifics needed for horizontal-ness vs vertical-ness. This feels the most correct but given that the object is composed of other objects you are then going to have proliferated throughout the view hierarchy going downwards.

Alternately, should I design one highly generalised class that has a property for orientation and then a lot of if/switch logic in the code to drive behaviour based on this. This feels like a code-smell.

Just go and create two separate similar but technically unrelated classes and just do a little more repeated typing. Since so many things are driven by the orientation this almost seems simpler than 1 above.

Or is there another alternative?

Other canonical examples where this would arise could be horizontal vs vertical:
– scrollers
– stacking panels

To attempt to clarify on regarding design goals and requirements, I would like the question answered in terms of how Apple Software Architects might have approached the NSScrollView class (or how any large organization might approach similar UI library code with “mirror” horizontal and vertical components).

The answer impacts several related vertical vs horizontal classes that aggregate these buttons into rows and columns respectively as the rows and columns themselves are also very similar save for the vertical vs horizontal orientation.

5

As a note up front, I am not familiar with how the Apple UI components commonly work and I mostly have experience working with Qt. This might influence the applicability of my answer.

I would start with a set of widgets that are orientation-neutral, but that can naturally be used where you expect an orientation-specific widget. For example a button where both dimensions can be set as fixed size or stretching and a grid with multiple rows and columns. These are concrete classes that can be used as-is.

With these orientation-agnostic widgets, a vertical button is just a button with a (relatively small) fixed-size width. And a row is just a grid with only one row.
How to realize this depends mostly on how the UI is typically being built.

  • If the UI is mostly coded by hand, you can create orientation-specific derived classes that do nothing more than set the appropriate defaults of their orientation-agnostic base classes. A VerticalButton class would only have a constructor to set the button’s width as a fixed value.
    This doesn’t prevent someone from changing the width back to being variable, but that would be their own fault.
  • If the UI is mostly generated from a graphical designer, I would look into the possibility of having the designer provide the widgets in multiple tastes (horizontal, vertical and orientation-agnostic) that instantiate each the same class with different settings.
    If that fails, I can always fall back to the first option.

Only if the orientation-specific widget needs behaviour that can’t be provided by the orientation-agnostic variant would I consider making a full-fledged class (with more than a constructor) for the orientation-specific widget.
For example, if the text on a vertical button needs to be rotated, but the regular button class doesn’t support text rotation.

Answering in a very abstract and technology/framework agnostic manner, my thinking is as follows

  • What a GUI control is (ie. volume up, volume down) not equates to how it is positioned in a window (a frame of visual reference).
  • Therefore separate the functionality of laying-out from the controls themselves.
  • Use a factory to create various layout managers for Controls (Control can be a common interface that all controls implements or provides – I suggest use composition – and provides information as required by the layout manager. For example a particular component may have a preferred width or height, similarly layout manager may want to instruct the control/component that it is now in a Horizontal layout thus dimensions are so..etc.)
  • in this case a LayoutFactory.createHorizontalLayoutManager().layout(List controls)

What does this facilitate

  • in the future you just need to modify / add / factories or methods in them to create more layout options.
  • LayoutFactory.createHorizontalLayoutManager().layout(List controls) is a Control (various controls like Button, ScrollBar..etc) agnostic. It just knows how to layout a component/control.
  • The control themselves are agnostic to target device (phone,TV,BillBoards,Laptop..etc)..that information can be incorporated into layout manager (even better, an concrete implementation of a Device interface would take a layout manager and it would know what a horizontal layout means in that particular device and render it accordingly)

two derived concrete classes for the specifics needed for horizontal-ness vs vertical-ness. This feels the most correct

Well, to me this feels mostly wrong. Your button can have a dozen properties or more like the orientation, for example it could be resizable, have a specific color, it could be labeled with an image, text or both, and so on. If you are going to create derivations for each property, even when you restrict yourself to properties which don’t change over the lifetime of the object, you will need an additional derivation for each combined property (for example, a VerticalResizableImageButton, HorizontalResizableImageButton, VerticalResizableTextButton, HorizontalResizableTextButton, each of those also in a non-resizable variant, and so on). Imagine how many different derivations this will mean in the end – each new property will multiply the number of needed derivations by a factor. I don’t think this is feasible.

should I design one highly generalised class that has a property for orientation and then a lot of if/switch logic in the code to drive behaviour

I would try to design one highly generalised class that has a property for the orientation, but as few conditional logic as possible. If the part of the code which depends on the orientation really ends up in many if/else statements, it can probably be encapsulated into one or more strategy objects, which are initialized once in the button constructor. For example, a “DragStrategy” (with derived classes “VerticalButtonDragStrategy” and “HorizontalButtonDragStrategy”) for controlling the drag-resizing.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật