Thiết kế hướng đối tượng


23

Giả sử bạn có những điều sau đây:

     +--------+     +------+
     | Animal |     | Food |
     +-+------+     +----+-+
       ^                 ^
       |                 |
       |                 |
  +------+              +-------+
  | Deer |              | Grass |
  +------+              +-------+

Deerkế thừa từ Animal, và Grasskế thừa từ Food.

Càng xa càng tốt. Animalđồ vật có thể ăn Foodđồ vật.

Bây giờ hãy trộn nó lên một chút. Cho phép thêm một Lionkế thừa từ Animal.

     +--------+     +------+
     | Animal |     | Food |
     +-+-----++     +----+-+
       ^     ^           ^
       |     |           |
       |     |           |
  +------+ +------+     +-------+
  | Deer | | Lion |     | Grass |
  +------+ +------+     +-------+

Bây giờ chúng ta có một vấn đề vì Lioncó thể ăn cả DeerGrass, nhưng Deerkhông được Foodnó là Animal.

Với việc sử dụng nhiều kế thừa và sử dụng thiết kế hướng đối tượng, làm thế nào để bạn giải quyết vấn đề này?

FYI: Tôi đã sử dụng http://www.asciiflow.com để tạo sơ đồ ASCII.


14
Mô hình hóa thế giới thực thường là vấn đề sớm hay muộn, bởi vì luôn có điều gì đó kỳ lạ xảy ra (như cá bay, cá hay chim? Nhưng chim cánh cụt là một con chim, không thể bay và ăn cá). Những gì @Ampt nói nghe có vẻ hợp lý, một Động vật nên có một bộ sưu tập những thứ nó ăn.
Rob van der Veer

2
Tôi nghĩ rằng động vật nên được thừa hưởng từ thực phẩm. Nếu thứ gì đó cố gắng ăn Sư tử, chỉ cần ném một UnlimitedOperationException.
RalphChapin

4
@RalphChapin: Tất cả các loại ăn sư tử (kền kền, bọ, v.v.). Tôi nghĩ rằng động vật và thực phẩm là sự phân biệt nhân tạo sẽ bị phá vỡ vì chúng không đủ rộng (cuối cùng tất cả động vật là một số thực phẩm động vật khác). Nếu bạn đã phân loại "LivingThing", bạn sẽ chỉ phải đối phó với các trường hợp cạnh với thực vật ăn những thứ không sống (khoáng chất, v.v.), và nó sẽ không phá vỡ bất cứ điều gì để có LivingT Breath.Eat (LivingThing).
Satanicpuppy

2
Chia sẻ nghiên cứu của bạn giúp mọi người. Hãy cho chúng tôi những gì bạn đã cố gắng và tại sao nó không đáp ứng nhu cầu của bạn. Điều này chứng tỏ rằng bạn đã dành thời gian để cố gắng tự giúp mình, nó giúp chúng ta tránh nhắc lại các câu trả lời rõ ràng và hầu hết nó giúp bạn có được câu trả lời cụ thể và phù hợp hơn. Xem thêm Cách hỏi
gnat

9
Câu hỏi này đã được trả lời bởi trò chơi Age of Empire III. ageofempires.wikia.com/wiki/List_of_Animals Thực hiện Deer và Gazelle IHuntable, Sheep và Cow IHerdable(được điều khiển bởi con người) và Lion chỉ thực hiện IAnimal, không ngụ ý bất kỳ giao diện nào. AOE3 hỗ trợ truy vấn bộ giao diện được hỗ trợ bởi một đối tượng cụ thể (tương tự instanceof) cho phép chương trình truy vấn các khả năng của nó.
rwong

Câu trả lời:


38

IS A mối quan hệ = Kế thừa

Sư tử là một con vật

ĐÃ có mối quan hệ = Thành phần

Xe có bánh xe

CÓ THỂ quan hệ = Giao diện

Tôi có thể ăn


5
+1 Điều đó thật đơn giản và lại là một bản tóm tắt hay về 3 loại mối quan hệ khác nhau
dreza

4
Thay thế: ICanBeEatenhoặcIEdible
Mike Weller

2
Mối quan hệ HAZ CÓ THỂ = lolcats
Steven A. Lowe

1
Làm thế nào để trả lời câu hỏi này?
dùng253751

13

OO chỉ là một phép ẩn dụ mô phỏng theo thế giới thực. Nhưng ẩn dụ chỉ đi rất xa.

Thông thường không có cách nào đúng để mô hình hóa một cái gì đó trong OO. Có một cách đúng đắn để làm điều đó cho một vấn đề cụ thể trong một tên miền cụ thể và bạn không nên hy vọng nó hoạt động tốt nếu bạn thay đổi vấn đề của mình, ngay cả khi các đối tượng miền giống nhau.

Tôi nghĩ rằng đây là một quan niệm sai lầm phổ biến nhất Comp. Tiếng Anh sinh viên có trong những năm đầu tiên của họ. OO không phải là một giải pháp phổ quát, chỉ là một công cụ tốt cho một số loại vấn đề có thể mô hình hóa miền của bạn một cách hợp lý.

Tôi đã không trả lời câu hỏi, chính xác vì chúng tôi thiếu thông tin tên miền. Nhưng với những điều trên, bạn có thể thiết kế một cái gì đó phù hợp với nhu cầu của bạn.


3
+1 OO là một công cụ, không phải là một tôn giáo.
mouviciel

Tôi đồng ý, có thể không có giải pháp hoàn hảo nếu vấn đề này tiếp tục thay đổi và phát triển. Trong tình trạng hiện tại, vấn đề này có thiếu thông tin tên miền để đưa ra giải pháp không?
Michael Irey

Bạn có nghiêm túc nghĩ rằng một thế giới thực đang được mô hình hóa trong OP? Một mô hình mối quan hệ được thể hiện thông qua một ví dụ.
Basilevs

@Basilevs Đó thực sự là một hàm ý, vì anh ta đề cập đến cách động vật cư xử trong cuộc sống thực. Người ta cần quan tâm đến lý do tại sao một người cần phải tính đến hành vi đó trong chương trình, IMO. Điều đó nói rằng, nó sẽ là tốt đẹp của tôi để đề xuất một số thiết kế có thể.
DPM

10

Bạn muốn chia nhỏ động vật thành các lớp con của chúng (hoặc ít nhất là theo ý nghĩa đối với những gì bạn đang làm). Cho rằng bạn đang làm việc với những gì trông giống như động vật cơ bản và hai loại thực phẩm (thực vật và thịt), sẽ rất hợp lý khi sử dụng động vật ăn thịt và động vật ăn cỏ để xác định thêm một con vật và giữ chúng tách biệt. Đây là những gì tôi đã vẽ cho bạn.

             +----------------+                   +--------------------+
             |    Animal      |                   |      Food          |
             |----------------|<--+Interfaces+--->|--------------------|
             |                |                   |                    |
             +----------------+                   +--------------------+
                +           +                       +                 +
                |           |    Abstract Classes   |                 |
                |           |        |          |   |                 |
                v           v        v          v   v                 v
   +-----------------+  +----------------+     +------------+      +------------+
   |   Herbivore     |  |  Carnivore     |     |   Plant    |      |   Meat     |
   |-----------------|  |----------------|     |------------|      |------------|
   |Eat(Plant p)     |  |Eat(Meat m)     |     |            |      |            |
   |                 |  |                |     |            |      |            |
   +-----------------+  +----------------+     +------------+      +------------+
            +                    +                    +                   +
            |                    |                    |                   |
            v                    v                    v                   v
   +-----------------+  +----------------+     +------------+      +------------+
   |  Deer           |  |   Lion         |     |  Grass     |      |  DeerMeat  |
   |-----------------|  |----------------|     |------------|      |------------|
   |DeerMeat Die()      |void Kill(Deer) |     |            |      |            |
   +-----------------+  +----------------+     +------------+      +------------+
                                 ^                    ^
                                 |                    |
                                 |                    |
                              Concrete Classes -------+

Như bạn có thể thấy, cả hai đều đưa ra một phương pháp ăn, nhưng những gì họ ăn thay đổi. Bây giờ Sư tử có thể giết một con nai, con nai có thể chết và trả lại DeerMeat, và câu hỏi ban đầu của OP về cách cho phép sư tử ăn một con nai nhưng không được trả lời cỏ mà không cần thiết kế toàn bộ hệ sinh thái.

Tất nhiên, điều này trở nên thú vị rất nhanh bởi vì Hươu cũng có thể được coi là một loại thịt, nhưng để đơn giản, tôi sẽ tạo ra một phương thức gọi là kill () dưới con nai, trả lại thịt hươu và đặt nó như một lớp bê tông kéo dài thịt.


Deer sẽ lộ giao diện IMeat chứ?
Dan Pichelman

Thịt không phải là một giao diện, nó là một lớp trừu tượng. Tôi đã thêm cách tôi sẽ thực hiện điều đó cho bạn
Ampt

Eat(Plant p)Eat(Meat m)cả hai đều vi phạm LSP.
Tulains Córdova

Làm thế nào vậy @ user61852? Tôi cố tình không phơi bày Ăn trong giao diện động vật để mỗi loại động vật có thể có phương pháp ăn riêng.
Ampt

1
TCWL (Quá phức tạp, sẽ rò rỉ). Vấn đề được phân phối và nổi lên và giải pháp của bạn là tĩnh, tập trung và được xác định trước. TCWL.
Tulains Córdova

7

Thiết kế của tôi sẽ như thế này:

  1. Thực phẩm được tuyên bố là giao diện; có một giao diện IFood và hai giao diện phái sinh từ nó: IMeat và IV Donable
  2. Động vật thực hiện IMeat và Rau thực hiện IV.
  3. Động vật có hai con cháu, Động vật ăn thịt và Hebivores
  4. Động vật ăn thịt có phương pháp Ăn nhận được một ví dụ của IMeat
  5. Động vật ăn cỏ có phương pháp Ăn nhận được một ví dụ của IV ăn được
  6. Sư tử xuống từ Carnivore
  7. Hươu xuống từ Động vật ăn cỏ
  8. Cỏ xuống từ Rau

Bởi vì Động vật thực hiện IMeat và Deer là một Động vật (Động vật ăn cỏ), Sư tử, là một Động vật (Động vật ăn thịt) có thể ăn IMeat cũng có thể ăn Hươu.

Hươu là một động vật ăn cỏ, vì vậy nó có thể ăn Cỏ vì nó thực hiện IV.

Động vật ăn thịt có thể ăn được IVegizable và động vật ăn cỏ có thể ăn IMeat.


1
Tôi đang thấy rất nhiều kiểu liệt kê ở đây chỉ sử dụng tính kế thừa để hạn chế khi các kiểu được thừa kế không thực hiện được gì ... Bất cứ khi nào bạn thấy mình tạo ra các loại không thực hiện bất kỳ chức năng nào, đó là một bước chân; bạn đã mở rộng một mô hình trong hệ thống loại không mang lại giá trị cho khả năng sử dụng mã
Jimmy Hoffa

Hãy nhớ hơn những loài ăn tạp tồn tại, như con người, vượn và gấu.
Tulains Córdova

Vậy làm thế nào để bạn thêm rằng cả hai, sư tử và hươu, là động vật có vú? :-)
johannes

2
@JimmyHoffa Chúng được gọi là "giao diện đánh dấu" và là cách sử dụng giao diện hoàn toàn hợp lệ. Nó cần được xem xét mã để quyết định xem việc sử dụng có hợp lý hay không, nhưng có nhiều trường hợp sử dụng (chẳng hạn như trường hợp này, khi Sư tử cố ăn Grass sẽ ném ngoại lệ NoInterface). Giao diện đánh dấu (hoặc thiếu) phục vụ để báo trước một ngoại lệ sẽ được ném nếu một phương thức được gọi với các đối số không được hỗ trợ.
rwong

1
@rwong Tôi hiểu khái niệm, chưa bao giờ nghe nó chính thức trước đây; chỉ có kinh nghiệm của tôi là mỗi khi một cơ sở mã mà tôi đang làm việc có chúng, nó làm cho mọi thứ phức tạp hơn và khó bảo trì hơn. Có lẽ kinh nghiệm của tôi tuy nhiên chỉ là nơi mọi người sử dụng chúng sai.
Jimmy Hoffa

5

Những loại thức ăn mà động vật có thể ăn không thực sự tạo thành một hệ thống phân cấp, trong trường hợp này, tự nhiên không thể phù hợp với mô hình hướng đối tượng đơn giản (lưu ý rằng ngay cả khi nó đã làm, động vật sẽ phải thừa hưởng từ thực phẩm, vì đó là thức ăn).

Kiến thức về những loại thực phẩm mà động vật có thể ăn không thể sống hoàn toàn với một trong hai lớp, vì vậy chỉ cần tham khảo một số thành viên trong hệ thống phân cấp thực phẩm là không đủ để cho bạn biết những gì bạn có thể ăn.

Đó là một mối quan hệ nhiều đến nhiều. Điều này có nghĩa là mỗi khi bạn thêm một con vật, bạn cần tìm ra nó có thể ăn gì và mỗi khi bạn thêm một loại thức ăn, bạn cần tìm ra những gì có thể ăn nó. Việc có thêm cấu trúc để khai thác hay không phụ thuộc vào động vật và thực phẩm bạn đang làm mẫu.

Nhiều kế thừa không thực sự giải quyết điều này rất tốt. Bạn cần một số loại bộ sưu tập những thứ mà một con vật có thể ăn, hoặc của những con vật có thể ăn một loại thực phẩm.


Giống như họ nói về regex "Tôi gặp vấn đề nên tôi đã sử dụng regex, bây giờ tôi có hai vấn đề", MI có dòng chữ "Tôi gặp vấn đề nên tôi đã sử dụng MI, bây giờ tôi có 99 vấn đề" Nếu tôi là bạn tôi ' d theo đó là vô ích mà bạn đã chọc vào đây mặc dù thực phẩm biết những gì có thể ăn nó, điều này thực sự đơn giản hóa mô hình một tấn. Phụ thuộc đảo ngược FTW.
Jimmy Hoffa

1

Tôi sẽ tiếp cận vấn đề từ nhiều phía khác nhau: OOP là về hành vi. Trong trường hợp của bạn, Grasscó một số hành vi là con của Food? Vì vậy, trong trường hợp của bạn, sẽ không có Grasslớp học, hoặc ít nhất, nó sẽ không được kế thừa từ đó Food. Ngoài ra, nếu bạn cần thực thi những người có thể ăn những gì vào thời gian biên dịch, có thể nghi ngờ nếu bạn cần Animaltrừu tượng hóa. Ngoài ra, không hiếm khi thấy động vật ăn thịt ăn cỏ , mặc dù không phải để nuôi dưỡng.

Vì vậy, tôi sẽ thiết kế nó như là (sẽ không bận tâm với nghệ thuật ASCI):

IEdiblevới tài sản Typelà enum của thịt, thực vật, thân thịt, v.v. (điều này sẽ không thay đổi thường xuyên và không có bất kỳ hành vi cụ thể nào, do đó không cần phải mô hình hóa điều này như là tìm kiếm lớp học).

Animalvới các phương thức CanEat(IEdible food)Eat(IEdible food), đó là logic. Sau đó, các động vật cụ thể có thể kiểm tra bất cứ khi nào có thể ăn thức ăn được cung cấp trong các trường hợp cụ thể và sau đó ăn thức ăn đó để đạt được nguồn gốc / làm một cái gì đó khác. Ngoài ra, tôi sẽ mô hình hóa các lớp Carnivore, Herbivore, Omnivore theo mô hình Chiến lược , hơn là một phần của hệ thống phân cấp động vật.


1

TL; DR: Thiết kế hoặc mô hình với bối cảnh.

Tôi nghĩ rằng câu hỏi của bạn là khó khăn vì nó thiếu bối cảnh của vấn đề thực tế mà bạn đang cố gắng giải quyết. Bạn có một số mô hình và một số mối quan hệ, nhưng thiếu khung mà nó cần để làm việc. Không có ngữ cảnh, mô hình hóa và ẩn dụ không hoạt động tốt để lại cánh cửa mở cho nhiều cách hiểu.

Tôi nghĩ sẽ hiệu quả hơn khi tập trung vào cách dữ liệu sẽ được tiêu thụ. Khi bạn có mô hình sử dụng dữ liệu, sẽ dễ dàng làm việc ngược hơn với các mô hình và mối quan hệ nên là gì.

Ví dụ, các yêu cầu chi tiết hơn sẽ đòi hỏi các mối quan hệ đối tượng khác nhau:

  • hỗ trợ Animals eating không FoodthíchGastroliths
  • hỗ trợ Chocolatenhư Poisoncho Dogs, nhưng không choHumans

Nếu chúng ta bắt đầu thực hiện cách mô hình hóa mối quan hệ đơn giản được trình bày Giao diện thực phẩm có thể là tốt nhất; và nếu đó là tổng số làm thế nào các mối quan hệ trong hệ thống thì tiền phạt của bạn. Tuy nhiên, chỉ một vài yêu cầu hoặc mối quan hệ bổ sung có thể ảnh hưởng lớn đến các mô hình và mối quan hệ đã hoạt động trong trường hợp đơn giản hơn.


Tôi đồng ý nhưng đó chỉ là một ví dụ nhỏ mà một người sói không cố gắng mô hình hóa thế giới. Ví dụ, bạn có thể có một con Cá mập ăn Lốp và Biển số. Bạn chỉ có thể tạo một lớp trừu tượng cha mẹ bằng một phương thức ăn bất kỳ loại đối tượng nào và Thực phẩm có thể mở rộng lớp kiêng này.
hagensoft

@hagensoft: Đồng ý. Đôi khi tôi bị mang đi bởi vì tôi liên tục thấy các nhà phát triển mô hình hóa dựa trên một phép ẩn dụ mà họ lập tức nắm bắt, thay vì nhìn vào cách dữ liệu cần được tiêu thụ và sử dụng. Họ kết hôn với một thiết kế OO dựa trên một ý tưởng ban đầu và sau đó thử và buộc vấn đề phù hợp với giải pháp của họ thay vì làm cho giải pháp của họ phù hợp với vấn đề.
Dietbuddha

1

Phương pháp tiếp cận thừa kế thành phần ECS:

An entity is a collection of components.
Systems process entities through their components.

Lion has claws and fangs as weapons.
Lion has meat as food.
Lion has a hunger for meat.
Lion has an affinity towards other lions.

Deer has antlers and hooves as weapons.
Deer has meat as food.
Deer has a hunger for plants.

Grass has plant as food.

Mã giả:

lion = new Entity("Lion")
lion.put(new Claws)
lion.put(new Fangs)
lion.put(new Meat)
lion.put(new MeatHunger)
lion.put(new Affinity("Lion"))

deer = new Entity("Deer")
deer.put(new Antlers)
deer.put(new Hooves)
deer.put(new PlantHunger)

grass = new Entity("Grass")
grass.put(new Plant)

Naturelà một systemvòng lặp thông qua các thực thể này, tìm kiếm những thành phần nào chúng có thông qua chức năng truy vấn tổng quát. Naturesẽ khiến các thực thể đói thịt tấn công các thực thể khác có thịt làm thực phẩm sử dụng vũ khí của họ, trừ khi họ có ái lực với thực thể đó. Nếu cuộc tấn công thành công, thực thể sẽ ăn thịt nạn nhân của mình, lúc đó nạn nhân sẽ biến thành một xác chết bị tước thịt. Naturesẽ khiến các thực thể đói thực vật phải ăn các thực thể có thực vật làm thực phẩm, miễn là chúng tồn tại.

Nature({lion, deer, grass})

Nature(entities)
{
    for each entity in entities:
    {
       if entity.has("MeatHunger"):
           attack_meat(entity, entities.with("Meat", exclude = entity))
       if entity.has("PlantHunger"):
           eat_plants(entity, entites.with("Plant", exclude = entity))
    }
}

Có lẽ chúng tôi muốn mở rộng Grassđể có nhu cầu về ánh sáng mặt trời và nước, và chúng tôi muốn giới thiệu ánh sáng mặt trời và nước vào thế giới của chúng tôi. Tuy nhiên, Grasskhông thể tìm kiếm chúng trực tiếp, vì nó không có mobility. Animalscũng có thể cần nước, nhưng có thể chủ động tìm kiếm nó vì họ có mobility. Thật dễ dàng để tiếp tục mở rộng và thay đổi mô hình này mà không làm vỡ tầng của toàn bộ thiết kế, vì chúng tôi chỉ cần thêm các thành phần mới và mở rộng hoạt động của các hệ thống của chúng tôi (hoặc số lượng hệ thống).


0

Với việc sử dụng nhiều kế thừa và sử dụng thiết kế hướng đối tượng, làm thế nào để bạn giải quyết vấn đề này?

Giống như hầu hết mọi thứ, nó phụ thuộc .

Nó phụ thuộc vào những gì bạn thấy "vấn đề này".

  • Đây có phải là một vấn đề triển khai chung không , ví dụ: làm thế nào để "giải quyết" sự vắng mặt của nhiều kế thừa trong nền tảng bạn đã chọn?
  • Đây có phải là một vấn đề thiết kế chỉ dành cho trường hợp cụ thể này , ví dụ như làm thế nào để mô hình thực tế rằng động vật cũng là thực phẩm?
  • Đây có phải là một vấn đề triết học với mô hình miền , ví dụ: 'thực phẩm' và 'động vật' hợp lệ, cần thiết và đủ phân loại cho ứng dụng thực tế được hình dung?

Nếu bạn đang hỏi về vấn đề triển khai chung, câu trả lời sẽ phụ thuộc vào khả năng của môi trường của bạn. Giao diện IFood và IAnimal có thể hoạt động, với lớp con EdibleAnimal thực hiện cả hai giao diện. Nếu môi trường của bạn không hỗ trợ giao diện, chỉ cần tạo Animal kế thừa từ Thực phẩm.

Nếu bạn đang hỏi về vấn đề thiết kế cụ thể này, chỉ cần tạo Animal kế thừa từ Thực phẩm. Đó là điều đơn giản nhất có thể làm việc.

Nếu bạn đang hỏi về các khái niệm thiết kế này, câu trả lời phụ thuộc mạnh mẽ vào những gì bạn định làm với mô hình. Nếu đó là một trò chơi video ăn thịt chó hoặc thậm chí là một ứng dụng để theo dõi lịch trình cho ăn tại sở thú, thì nó có thể đủ để làm việc. Nếu đó là một mô hình khái niệm cho các mô hình hành vi động vật, thì có lẽ nó hơi nông.


0

Kế thừa nên được sử dụng cho một cái gì đó luôn luôn là một cái gì đó khác, và không thể thay đổi. Cỏ không phải lúc nào cũng là thức ăn. Ví dụ, tôi không ăn cỏ.

Cỏ đóng vai trò là thực phẩm cho một số động vật.


Nó chỉ là một sự trừu tượng. Nếu đó là một yêu cầu thì bạn có thể tạo ra nhiều bộ phận mở rộng lớp trừu tượng Thực vật và khiến con người ăn một lớp trừu tượng như 'HumanEitablePlants' để nhóm các loài thực vật ăn vào các lớp cụ thể.
hagensoft

0

Bạn vừa đi qua giới hạn cơ bản của OO.

OO hoạt động tốt với các cấu trúc phân cấp. Nhưng một khi bạn thoát khỏi hệ thống phân cấp nghiêm ngặt thì sự trừu tượng không hoạt động tốt như vậy.

Tôi biết tất cả về các chế phẩm biến thái, v.v ... được sử dụng để khắc phục những hạn chế này nhưng chúng vụng về, và quan trọng hơn là dẫn đến mã tối nghĩa và khó theo dõi.

Các cơ sở dữ liệu quan hệ được phát minh chủ yếu để thoát khỏi những hạn chế của các cấu trúc phân cấp nghiêm ngặt.

Lấy ví dụ cỏ của bạn cũng có thể là vật liệu xây dựng, nguyên liệu thô cho giấy, vật liệu quần áo, cỏ dại hoặc cây trồng.

Một con nai có thể là vật nuôi, gia súc, động vật trong vườn thú hoặc một loài được bảo vệ.

Một con sư tử cũng có thể là một động vật trong vườn thú hoặc một loài được bảo vệ.

Cuộc sống không đơn giản.


0

Với việc sử dụng nhiều kế thừa và sử dụng thiết kế hướng đối tượng, làm thế nào để bạn giải quyết vấn đề này?

Có vấn đề gì vậy? Hệ thống này làm gì?Cho đến khi bạn trả lời, tôi không biết lớp nào có thể được yêu cầu. Bạn đang cố gắng mô hình hóa một hệ sinh thái, với động vật ăn thịt và động vật ăn cỏ và thực vật, dự kiến ​​các quần thể loài trong tương lai? Bạn đang cố gắng để máy tính chơi 20 câu hỏi?

Thật lãng phí thời gian để bắt đầu thiết kế trước khi bất kỳ trường hợp sử dụng nào được xác định. Tôi đã thấy điều này được đưa đến những thái cực kỳ cục khi một nhóm khoảng mười người bắt đầu sản xuất một mô hình OO của Hãng hàng không bằng phần mềm thông qua hình ảnh. Họ đã làm việc trong hai năm với nghề người mẫu mà không có vấn đề kinh doanh thực tế nào trong đầu. Cuối cùng, khách hàng đã mệt mỏi chờ đợi và yêu cầu nhóm giải quyết một vấn đề thực tế. Tất cả những mô hình đó là hoàn toàn vô dụng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.