{"id":5184,"date":"2021-03-31T13:07:00","date_gmt":"2021-03-31T17:07:00","guid":{"rendered":"https:\/\/xp123.com\/articles\/?p=5184"},"modified":"2021-03-28T20:21:41","modified_gmt":"2021-03-29T00:21:41","slug":"set-like-objects-tdd-patterns","status":"publish","type":"post","link":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/","title":{"rendered":"Set-Like Objects &#8211; TDD Patterns"},"content":{"rendered":"\n<p>Sets are fundamental in mathematics \u2014 and programming. We&#8217;ll look at some considerations when using Test-Driven Development (TDD) for set-like objects.<\/p>\n\n\n\n<p>This is the last in a series of articles describing TDD for container objects; see the <a href=\"#references\">References<\/a> for the others.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The Jobs of a Set<\/h2>\n\n\n\n<p>Sets provide several common operations (see <a href=\"#references\">References<\/a>):<\/p>\n\n\n\n<p><strong>Membership Testing<\/strong> &#8211; determine whether something is in, or not in, a set.<\/p>\n\n\n\n<p><strong>Iteration<\/strong> &#8211; deliver the members of a set one at a time. <\/p>\n\n\n\n<p><strong>Set Algebra Operations<\/strong> &#8211; form the union, intersection, complement, etc. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Representations<\/h2>\n\n\n\n<p>A fundamental idea like &#8220;set&#8221; has many possible representations:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Bit String<\/h3>\n\n\n\n<p>For sets with a small range, a string of bits can represent the set. For example, if values have the range 0..63, a 64-bit unsigned integer can have the corresponding bit set. For a moderate range, with approximately equal likelihood of being in or out, operations tend to be very quick. In the best case, they&#8217;re simple hardware-level instructions like &#8220;and&#8221;, &#8220;or&#8221;, &#8220;xor&#8221;, or bit shift. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">List<\/h3>\n\n\n\n<p>Store the items of a set in a list. You must preserve the constraint (or the illusion) that each item is only stored once. <\/p>\n\n\n\n<p>With lists, operations are often O(n) &#8211; proportional to the length of the list. Some linked-list approaches move the most recently accessed item to the front, which can speed up some operations. Variations such as the <em>skip list<\/em> (see <a href=\"#references\">References<\/a>) attempt to average O(log n) performance.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Hash Table<\/h2>\n\n\n\n<p>By defining a function that maps any element to a number, you can store items in a (typically) sparse array of values. You can do a lookup in O(1) on average.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tree<\/h3>\n\n\n\n<p>By storing elements in trees, you may be able to get O(log n) access. In general, this requires self-balancing structures such as red-black trees.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Etc.<\/h3>\n\n\n\n<p>Just about any container type can be used for sets: heaps, tries, arrays, and so on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Set-Like Objects<\/h2>\n\n\n\n<p>Set-like objects share some characteristics or operations with sets, but also have differences. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Multi-set aka Bag<\/h3>\n\n\n\n<p>A multi-set is a set that allows repetition &#8211; the same element can be in the set multiple times. For example, think of a wallet containing a ten, and five, and three ones. You care about the denominations <em>and<\/em> their counts. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ordered Set<\/h3>\n\n\n\n<p>Some applications require a set to iterate in a particular order. If the set can do it, it saves you from having to iterate the items, store them in a structure, sort them, and iterate through the result. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Map<\/h2>\n\n\n\n<p>A map (e.g., a hash table) can represent a set (by using an element as a key, and mapping the key to itself or a constant), but it can also represent the mapping (a function) from an element to some other object. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Database<\/h3>\n\n\n\n<p>SQL (and other) databases have set behaviors at their core. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Spelling List <\/h3>\n\n\n\n<p>One of the early Unix <code>spell<\/code> implementations (see <a href=\"#references\">References<\/a>) used a one-sided membership test. If the list said &#8220;no&#8221; then a word definitely was not in the vocabulary list. But if the list said said &#8220;yes&#8221;, odds are it&#8217;s a good word, but it might be misspelled. (The implementation worked by running vocabulary words through multiple hash functions, and storing the results of each. Usually a misspelled word would &#8220;miss&#8221; at least one hash, but could by chance make it through all of them.) <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Symbol Table<\/h3>\n\n\n\n<p>In a previous article, we described symbol tables as a tree-like object (see <a href=\"#references\">References<\/a>). But a symbol table also acts like a set, as you retrieve name information, and iterate through the list of names. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Test-Driving Sets<\/h2>\n\n\n\n<p>As with lists or trees, <em>sufficient completeness<\/em> can give you good ideas for driving set-like objects: Identify the ways to build and mutate an object, then verify that each &#8220;observer&#8221; method behaves as it should. <\/p>\n\n\n\n<p>You also may find invariants helpful &#8211; they should start true when the object is built, and remain true after any possible mutation. <\/p>\n\n\n\n<p>With so many varieties of implementations, you may find that you have to focus on specific situations that your algorithm addresses. This is common when an abstract data type has multiple implementations: the public interface makes things sound simple, but the data structure may have special handling for certain situations. <\/p>\n\n\n\n<p>For example, if your representation is a self-balancing tree, you&#8217;ll need examples that trigger the self-balancing behavior. It&#8217;s common for the sequence of operations to matter: <code>set.add(a).add(b)<\/code> may have a different representation than <code>set.add(b).add(a)<\/code>. You may need very complex data to trigger all the situations you want. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Opening up the Box<\/h3>\n\n\n\n<p>When the internal representation varies enough from the public interface, you may need to reveal more to test it thoroughly.<\/p>\n\n\n\n<p>There are two common approaches:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Expose more information to the test (e.g., with access modifiers).<\/li><li>Split the class into a public interface that delegates to a specific implementation, and test the implementation directly. <\/li><\/ol>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><a href=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/03\/impl.png\"><img loading=\"lazy\" decoding=\"async\" width=\"550\" height=\"299\" src=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/03\/impl.png\" alt=\"Split the interface and implementation apart, delegating from the original class to the implementation, so you can test more thoroughly\" class=\"wp-image-5185\" srcset=\"https:\/\/xp123.com\/wp-content\/uploads\/2021\/03\/impl.png 550w, https:\/\/xp123.com\/wp-content\/uploads\/2021\/03\/impl-300x163.png 300w\" sizes=\"auto, (max-width: 550px) 100vw, 550px\" \/><\/a><\/figure><\/div>\n\n\n\n<p> This is like splitting a large class: Your implementation tests benefit from a richer interface, but the &#8220;surface area&#8221; of the system has grown.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>We looked at the basic operations for sets, then several common implementations: bit string, list, map, tree, etc. We considered some set-like objects too: multi-set, ordered set, map, spelling list, database, and symbol table. These are like sets, but have some difference, e.g., in sorting or duplicate handling. <\/p>\n\n\n\n<p>Finally, we talked about using sufficient completeness as a testing pattern: consider all the ways to create and mutate objects, and what that does to &#8220;observer&#8221; methods. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"references\">References<\/h2>\n\n\n\n<p>&#8220;<a href=\"https:\/\/ia800805.us.archive.org\/33\/items\/development-of-spelling-list\/Image092317125441.pdf\" target=\"_blank\" rel=\"noreferrer noopener\">Development of a Spelling List<\/a>&#8220;, by M. Douglas McIlroy. From <em>IEEE Transactions on Communications<\/em>, Vol. COM-30, No. 1, January, 1982. <\/p>\n\n\n\n<p>&#8220;<a href=\"https:\/\/xp123.com\/articles\/list-like-objects-tdd-patterns\/\" target=\"_blank\" rel=\"noreferrer noopener\">List-Like Objects &#8211; TDD Patterns<\/a>&#8220;, by Bill Wake. Retrieved 2021-03-28. <\/p>\n\n\n\n<p>&#8220;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Set_(abstract_data_type)\" target=\"_blank\" rel=\"noreferrer noopener\">Set (abstract data type)<\/a>&#8220;, Wikipedia. Retrieved 2021-03-28.<\/p>\n\n\n\n<p>&#8220;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Skip_list\" target=\"_blank\" rel=\"noreferrer noopener\">Skip list<\/a>&#8220;, Wikipedia. Retrieved 2021-03-28.<\/p>\n\n\n\n<p>&#8220;<a href=\"https:\/\/xp123.com\/articles\/tree-like-objects-tdd-patterns\/\" target=\"_blank\" rel=\"noreferrer noopener\">Tree-Like Objects &#8211; TDD Patterns<\/a>&#8220;, by Bill Wake. Retrieved 2021-03-28. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sets are fundamental in mathematics \u2014 and programming. We&#8217;ll look at some considerations when using Test-Driven Development (TDD) for set-like objects. This is the last in a series of articles describing TDD for container objects; see the References for the <a class=\"more-link\" href=\"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/\">Continue reading <span class=\"screen-reader-text\">  Set-Like Objects &#8211; TDD Patterns<\/span><span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_wp_convertkit_post_meta":{"form":"-1","landing_page":"0","tag":"0","restrict_content":"0"},"footnotes":""},"categories":[1],"tags":[77,97,109],"class_list":["post-5184","post","type-post","status-publish","format-standard","hentry","category-xp123","tag-prog","tag-tdd","tag-xp"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Set-Like Objects - TDD Patterns - XP123 - TDD for Containers<\/title>\n<meta name=\"description\" content=\"Sets are fundamental in mathematics and programming. We&#039;ll look at Test-Driven Development (TDD) for set-like objects\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Bill Wake\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/\"},\"author\":{\"name\":\"Bill Wake\",\"@id\":\"https:\\\/\\\/xp123.com\\\/#\\\/schema\\\/person\\\/72474af0de7f699327fcff15bebf04c9\"},\"headline\":\"Set-Like Objects &#8211; TDD Patterns\",\"datePublished\":\"2021-03-31T17:07:00+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/\"},\"wordCount\":968,\"publisher\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/#\\\/schema\\\/person\\\/72474af0de7f699327fcff15bebf04c9\"},\"image\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/impl.png\",\"keywords\":[\"programmer\",\"tdd\",\"XPlorations\"],\"articleSection\":[\"xp123.com\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/\",\"url\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/\",\"name\":\"Set-Like Objects - TDD Patterns - XP123 - TDD for Containers\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/impl.png\",\"datePublished\":\"2021-03-31T17:07:00+00:00\",\"description\":\"Sets are fundamental in mathematics and programming. We'll look at Test-Driven Development (TDD) for set-like objects\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/#primaryimage\",\"url\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/impl.png\",\"contentUrl\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2021\\\/03\\\/impl.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/xp123.com\\\/set-like-objects-tdd-patterns\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/xp123.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Set-Like Objects &#8211; TDD Patterns\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/xp123.com\\\/#website\",\"url\":\"https:\\\/\\\/xp123.com\\\/\",\"name\":\"XP123\",\"description\":\"Exploring Extreme Programming\",\"publisher\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/#\\\/schema\\\/person\\\/72474af0de7f699327fcff15bebf04c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/xp123.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/xp123.com\\\/#\\\/schema\\\/person\\\/72474af0de7f699327fcff15bebf04c9\",\"name\":\"Bill Wake\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2022\\\/09\\\/bill2012.jpeg\",\"url\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2022\\\/09\\\/bill2012.jpeg\",\"contentUrl\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2022\\\/09\\\/bill2012.jpeg\",\"width\":200,\"height\":200,\"caption\":\"Bill Wake\"},\"logo\":{\"@id\":\"https:\\\/\\\/xp123.com\\\/wp-content\\\/uploads\\\/2022\\\/09\\\/bill2012.jpeg\"},\"sameAs\":[\"http:\\\/\\\/xp123.com\"],\"url\":\"https:\\\/\\\/xp123.com\\\/author\\\/bill\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Set-Like Objects - TDD Patterns - XP123 - TDD for Containers","description":"Sets are fundamental in mathematics and programming. We'll look at Test-Driven Development (TDD) for set-like objects","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/","twitter_misc":{"Written by":"Bill Wake","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/#article","isPartOf":{"@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/"},"author":{"name":"Bill Wake","@id":"https:\/\/xp123.com\/#\/schema\/person\/72474af0de7f699327fcff15bebf04c9"},"headline":"Set-Like Objects &#8211; TDD Patterns","datePublished":"2021-03-31T17:07:00+00:00","mainEntityOfPage":{"@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/"},"wordCount":968,"publisher":{"@id":"https:\/\/xp123.com\/#\/schema\/person\/72474af0de7f699327fcff15bebf04c9"},"image":{"@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/#primaryimage"},"thumbnailUrl":"https:\/\/xp123.com\/wp-content\/uploads\/2021\/03\/impl.png","keywords":["programmer","tdd","XPlorations"],"articleSection":["xp123.com"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/","url":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/","name":"Set-Like Objects - TDD Patterns - XP123 - TDD for Containers","isPartOf":{"@id":"https:\/\/xp123.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/#primaryimage"},"image":{"@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/#primaryimage"},"thumbnailUrl":"https:\/\/xp123.com\/wp-content\/uploads\/2021\/03\/impl.png","datePublished":"2021-03-31T17:07:00+00:00","description":"Sets are fundamental in mathematics and programming. We'll look at Test-Driven Development (TDD) for set-like objects","breadcrumb":{"@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/xp123.com\/set-like-objects-tdd-patterns\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/#primaryimage","url":"https:\/\/xp123.com\/wp-content\/uploads\/2021\/03\/impl.png","contentUrl":"https:\/\/xp123.com\/wp-content\/uploads\/2021\/03\/impl.png"},{"@type":"BreadcrumbList","@id":"https:\/\/xp123.com\/set-like-objects-tdd-patterns\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/xp123.com\/"},{"@type":"ListItem","position":2,"name":"Set-Like Objects &#8211; TDD Patterns"}]},{"@type":"WebSite","@id":"https:\/\/xp123.com\/#website","url":"https:\/\/xp123.com\/","name":"XP123","description":"Exploring Extreme Programming","publisher":{"@id":"https:\/\/xp123.com\/#\/schema\/person\/72474af0de7f699327fcff15bebf04c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/xp123.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/xp123.com\/#\/schema\/person\/72474af0de7f699327fcff15bebf04c9","name":"Bill Wake","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/xp123.com\/wp-content\/uploads\/2022\/09\/bill2012.jpeg","url":"https:\/\/xp123.com\/wp-content\/uploads\/2022\/09\/bill2012.jpeg","contentUrl":"https:\/\/xp123.com\/wp-content\/uploads\/2022\/09\/bill2012.jpeg","width":200,"height":200,"caption":"Bill Wake"},"logo":{"@id":"https:\/\/xp123.com\/wp-content\/uploads\/2022\/09\/bill2012.jpeg"},"sameAs":["http:\/\/xp123.com"],"url":"https:\/\/xp123.com\/author\/bill\/"}]}},"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/posts\/5184","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/comments?post=5184"}],"version-history":[{"count":1,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/posts\/5184\/revisions"}],"predecessor-version":[{"id":5188,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/posts\/5184\/revisions\/5188"}],"wp:attachment":[{"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/media?parent=5184"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/categories?post=5184"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/xp123.com\/wp-json\/wp\/v2\/tags?post=5184"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}