{"id":2782,"date":"2022-03-17T08:51:39","date_gmt":"2022-03-17T12:51:39","guid":{"rendered":"https:\/\/blogs.mathworks.com\/developer\/?p=2782"},"modified":"2022-03-17T08:51:39","modified_gmt":"2022-03-17T12:51:39","slug":"using-custom-classes-to-convey-intent","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/developer\/2022\/03\/17\/using-custom-classes-to-convey-intent\/","title":{"rendered":"You&#8217;ve Got Mail"},"content":{"rendered":"<div class=\"content\"><!--introduction--><!--\/introduction--><h4>Let&#8217;s send some emails!<a name=\"92a66472-8323-49eb-af77-982ea9eddbb2\"><\/a><\/h4><p>Imagine you write a function that sends an email to a customer. Your initial function call might look like this:<\/p><pre>  sendEmail(emailAddress,firstName,lastName,bodyText)<\/pre><p>Having 4 inputs to our function is fine, but if we need to add more customer details it becomes difficult to manage. When working on software projects, we find that certain variables tend to be grouped together. In our case, &#8220;first name&#8221;, &#8220;last name&#8221;, and &#8220;email address&#8221; represent a customer. We might also have &#8220;name&#8221;, &#8220;description&#8221;, and &#8220;price&#8221; to represent a product, or &#8220;customer&#8221;, &#8220;product&#8221;, and &#8220;datetime&#8221; to represent an order.<\/p><p>So let&#8217;s group our first 3 inputs into a single variable. The simplest way to do this is with a <a href=\"https:\/\/uk.mathworks.com\/help\/matlab\/ref\/struct.html\">struct<\/a>:<\/p><pre>  customer = struct(\"FirstName\",firstName,\"LastName\",lastName,\"Email\",emailAddress);<\/pre><p>Our function call then becomes:<\/p><pre>  sendEmail(customer,bodyText)<\/pre><p>The advantage of this is that we can now pass around all the information related to a customer as a single variable. If their postal address is added to the struct, it&#8217;s automatically available for us to use in our <tt>sendEmail<\/tt> function.<\/p><h4>What&#8217;s in a customer?<a name=\"814e6279-48d5-4942-9791-4e784bdb26f2\"><\/a><\/h4><p>A disadvantage arises when a new developer (or you several weeks from now!) looks at this function again. What exactly is <i>in<\/i> the &#8220;customer&#8221; struct? Is the field for their first name called &#8220;FirstName&#8221; or &#8220;Firstname&#8221; or &#8220;firstname&#8221;?<\/p><p>If you try to access a field that doesn&#8217;t exist, you&#8217;ll get an error, but if you set a field that didn&#8217;t previously exist, it will be automatically added to the struct. Maybe you can work out the correct names from the existing code, assuming it&#8217;s not too long or complex. Otherwise, you&#8217;ll have to run a test (because <a href=\"https:\/\/blogs.mathworks.com\/developer\/2021\/08\/31\/why-testing-is-worth-the-effort\/\">someone has written a test<\/a>, right?) and see what is provided to the function at runtime.<\/p><p>With a customer, we can at least take an educated guess as to the contents. If a more generic name is adopted (&#8220;data&#8221;, &#8220;metdadata&#8221;, &#8220;info&#8221;), it can be impossible.<\/p><p>This lack of clarity wastes developer time over and over again, and can cause subtle bugs that are hard to track down.<\/p><h4>What&#8217;s a valid customer?<a name=\"f385bc9d-2436-47c2-ac7d-983abb22f457\"><\/a><\/h4><p>To address this, we could define validation on the <tt>customer<\/tt> input: we want to make sure that we have a scalar struct with the correct field names, that the data types are correct, and that any other validation rules are met. For example, that the email address is always of the format &#8220;*@*.*&#8221; .<\/p><p>Managing this can be complex and laborious. If you&#8217;re not careful, it leads to scattered code that repeats the validation and that is difficult to read. Furthermore, can we <i>guarantee<\/i> that all such &#8220;customer structs&#8221; will always be valid? No &#8211; it&#8217;s possible for us, or another developer, to create an invalid customer struct and we won&#8217;t know about it until we run our validation again or the code errors.<\/p><p>This forms a second source of bugs &#8211; data that is not in the expected format. Common issues include variables that are empty but shouldn&#8217;t be, or a cellstr that should be a string array.<\/p><h4>What do we need from a customer?<a name=\"ce64fd97-0285-4bdb-bb27-4767f75dfa2e\"><\/a><\/h4><p>There are operations that we frequently need to perform on our customer struct. For example, constructing the customer&#8217;s full name from their first and last name:<\/p><pre>  fullname = customer.FirstName + \" \" + customer.LastName;<\/pre><p>Writing this code each time we need the full name either leads to code duplication (and a high likelihood of inconsistency), or a function that&#8217;s divorced from its data and potentially hard to find.<\/p><h4>Define a class instead<a name=\"2a56258b-ced4-49b6-bdab-86dd023a52ce\"><\/a><\/h4><p>Instead, we can <a href=\"https:\/\/uk.mathworks.com\/help\/matlab\/matlab_oop\/create-a-simple-class.html\">define a class<\/a> for our customer! Doing so will bring the following advantages:<\/p><p>Functions that use the customer class only need one line of validation in the arguments block &#8211; the required class. The validation line tells you exactly what the input is, and you can immediately hit <tt>Ctrl+D<\/tt> to go to the class definition. It forms a clear contract between the calling code and your class.<\/p><p>The properties block tells you exactly what properties <i>all<\/i> objects of that class will have. The validation for each property makes explicit what each property will contain, it can set default values, and it guarantees that all objects of the class will be valid.<\/p><p>Dependent properties can be added to give you derived information without having to poke around the internals of the object (hello <a href=\"https:\/\/blogs.mathworks.com\/developer\/2016\/08\/08\/han-solo-encapsulation\/\">encapsulation<\/a>!); <a href=\"https:\/\/martinfowler.com\/bliki\/TellDontAsk.html\">tell the object<\/a> what you want it to do, don&#8217;t ask for the individual pieces of data. Other functionality related to the class can be added as methods.<\/p><h4>Make your class work with arrays<a name=\"b6862f65-9a8a-4f17-ba13-9ecc90048c20\"><\/a><\/h4><p>Custom classes really begin to shine when you make them array compatible. Rather than having <i>a<\/i> customer or <i>an<\/i> order, you can have an array of customers or orders and perform operations on them in one go. This native array handling is one of the unique features of MATLAB and removes the need for a &#8220;collection&#8221; object like you might have in C.<\/p><p>An array-based method I almost always add is <tt>table<\/tt>. <tt>table<\/tt> transforms an array of objects into a standard MATLAB <a href=\"https:\/\/uk.mathworks.com\/help\/matlab\/ref\/table.html\">table<\/a>. It allows you to easily see the entire contents of the object array and perhaps to write the data into a <a href=\"https:\/\/uk.mathworks.com\/help\/matlab\/ref\/uitable.html\">uitable<\/a> for display or <a href=\"https:\/\/uk.mathworks.com\/help\/matlab\/ref\/writetable.html\">to a spreadsheet<\/a> for reporting purposes.<\/p><p>So why go to all this trouble of creating a custom class just to turn it back into a generic data type? The crucial difference now is that the table is <i>derived<\/i> from our custom class which handles all the validation and calculations; the table is not the source of truth.<\/p><h4>Code example<a name=\"ca124cfb-bd9f-4e95-a5fe-78b55bc5b499\"><\/a><\/h4><p>Below is example code showing what a customer might look like when implemented as a class in MATLAB:<\/p><div><ul><li>Property names are fixed, always present, and cannot be changed at runtime.<\/li><li>Data types and sizes are fixed, and type conversion performed automatically where possible (e.g. char to string).<\/li><li><tt>Email<\/tt> is validated whenever it is changed.<\/li><li>The <tt>FullName<\/tt> dependent property gives calling code direct access to what it actually wants.<\/li><li>The <tt>table<\/tt> method allows us to easily visualise the contents of a customer array and that data to be consumed outside of our application.<\/li><\/ul><\/div><pre class=\"language-matlab\">\r\n<span class=\"keyword\">classdef<\/span> Customer\r\n    \r\n    <span class=\"keyword\">properties<\/span>\r\n        FirstName (1,1) string\r\n        LastName (1,1) string\r\n        Email (1,1) string {mustBeValidEmail} = <span class=\"string\">\"undefined@domain.com\"<\/span>\r\n    <span class=\"keyword\">end<\/span>\r\n    \r\n    <span class=\"keyword\">properties<\/span> (Dependent,SetAccess = private)\r\n        FullName (1,1) string\r\n    <span class=\"keyword\">end<\/span>\r\n\r\n    <span class=\"keyword\">methods<\/span>\r\n        \r\n        <span class=\"keyword\">function<\/span> cust = Customer(first,last,email)\r\n            \r\n            cust.FirstName = first;\r\n            cust.LastName = last;\r\n            cust.Email = email;\r\n            \r\n        <span class=\"keyword\">end<\/span>\r\n        \r\n        <span class=\"keyword\">function<\/span> str = get.FullName(customer)\r\n            \r\n            str = customer.FirstName + <span class=\"string\">\" \"<\/span> + customer.LastName;\r\n            \r\n        <span class=\"keyword\">end<\/span>\r\n        \r\n        <span class=\"keyword\">function<\/span> tbl = table(customers)\r\n            \r\n            <span class=\"keyword\">arguments<\/span>\r\n                customers (1,:) Customer\r\n            <span class=\"keyword\">end<\/span>\r\n            \r\n            fn = [customers.FirstName]';\r\n            ln = [customers.LastName]';\r\n            email = [customers.Email]';\r\n            \r\n            tbl = table(fn,ln,email,<span class=\"string\">'VariableNames'<\/span>,[<span class=\"string\">\"FirstName\"<\/span> <span class=\"string\">\"LastName\"<\/span> <span class=\"string\">\"Email\"<\/span>]);\r\n            \r\n        <span class=\"keyword\">end<\/span>\r\n        \r\n    <span class=\"keyword\">end<\/span>\r\n    \r\n<span class=\"keyword\">end<\/span>\r\n\r\n<span class=\"keyword\">function<\/span> mustBeValidEmail(value)\r\n    \r\n    anyLetterOrNum = alphanumericsPattern();\r\n    pat = anyLetterOrNum + <span class=\"string\">\"@\"<\/span> + anyLetterOrNum + <span class=\"string\">\".\"<\/span> + anyLetterOrNum;\r\n    assert(matches(value,pat),<span class=\"string\">\"Customer:InvalidEmail\"<\/span>,<span class=\"string\">\"Invalid email\"<\/span>)\r\n    \r\n<span class=\"keyword\">end<\/span>\r\n\r\n<\/pre><p>Here&#8217;s how we might use it:<\/p><pre class=\"codeinput\">c(1) = Customer(<span class=\"string\">\"Mitch\"<\/span>,<span class=\"string\">\"Docker\"<\/span>,<span class=\"string\">\"mitch@foo.com\"<\/span>)\r\nc(2) = Customer(<span class=\"string\">\"Lachlan\"<\/span>,<span class=\"string\">\"Morton\"<\/span>,<span class=\"string\">\"lachlan@bah.com\"<\/span>);\r\nc(3) = Customer(<span class=\"string\">\"Rigoberto\"<\/span>,<span class=\"string\">\"Uran\"<\/span>,<span class=\"string\">\"rigo@uran.com\"<\/span>);\r\ntable(c)\r\n<\/pre><pre class=\"codeoutput\">\r\nc = \r\n\r\n  Customer with properties:\r\n\r\n    FirstName: \"Mitch\"\r\n     LastName: \"Docker\"\r\n        Email: \"mitch@foo.com\"\r\n     FullName: \"Mitch Docker\"\r\n\r\n\r\nans =\r\n\r\n  3&times;3 table\r\n\r\n     FirstName     LastName          Email      \r\n    ___________    ________    _________________\r\n\r\n    \"Mitch\"        \"Docker\"    \"mitch@foo.com\"  \r\n    \"Lachlan\"      \"Morton\"    \"lachlan@bah.com\"\r\n    \"Rigoberto\"    \"Uran\"      \"rigo@uran.com\"  \r\n\r\n<\/pre><p>We can validate the inputs to our <tt>sendEmail<\/tt> function with a simple arguments block:<\/p><pre class=\"language-matlab\">\r\n<span class=\"keyword\">function<\/span> sendEmail(customer,bodyText)\r\n    \r\n    <span class=\"keyword\">arguments<\/span>\r\n        customer (1,1) Customer\r\n        bodyText (1,1) string\r\n    <span class=\"keyword\">end<\/span>\r\n    \r\n    <span class=\"comment\">% Other code...<\/span>\r\n    \r\n<span class=\"keyword\">end<\/span>\r\n\r\n<\/pre><h4>When should I define a custom class?<a name=\"e9617428-62a8-41cb-8719-6d6d562161bb\"><\/a><\/h4><p>You may be wondering at what point you should go to the effort and formality of creating custom classes. Much like making the decision to go from a script to a function or a function to a class, it&#8217;s when you hit the limits of what your current implementation can do. If you find that:<\/p><div><ul><li>It&#8217;s difficult to understand what&#8217;s in your data structure.<\/li><li>You have problems with validation.<\/li><li>Code that&#8217;s closely related to the data is duplicated, scattered, or inconsistent.<\/li><\/ul><\/div><p>It&#8217;s time to think about custom classes.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_f3bb216fc38f43f48451dab42fbc494f() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='f3bb216fc38f43f48451dab42fbc494f ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' f3bb216fc38f43f48451dab42fbc494f';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2022 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_f3bb216fc38f43f48451dab42fbc494f()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2022a<br><\/p><\/div><!--\r\nf3bb216fc38f43f48451dab42fbc494f ##### SOURCE BEGIN #####\r\n%% You\u2019ve got mail\r\n%% Let\u2019s send some emails!\r\n% Imagine you write a function that sends an email to a customer. Your initial \r\n% function call might look like this:\r\n%\r\n%    sendEmail(emailAddress,firstName,lastName,bodyText)\r\n%% \r\n% Having 4 inputs to our function is fine, but if we need to add more customer \r\n% details it becomes difficult to manage. When working on software projects, we \r\n% find that certain variables tend to be grouped together. In our case, \u201cfirst \r\n% name\u201d, \u201clast name\u201d, and \u201cemail address\u201d represent a customer. We might also \r\n% have \u201cname\u201d, \u201cdescription\u201d, and \u201cprice\u201d to represent a product, or \u201ccustomer\u201d, \r\n% \u201cproduct\u201d, and \u201cdatetime\u201d to represent an order.\r\n% \r\n% So let\u2019s group our first 3 inputs into a single variable. The simplest way \r\n% to do this is with a <https:\/\/uk.mathworks.com\/help\/matlab\/ref\/struct.html struct>:\r\n%\r\n%    customer = struct(\"FirstName\",firstName,\"LastName\",lastName,\"Email\",emailAddress);\r\n%% \r\n% Our function call then becomes:\r\n%\r\n%    sendEmail(customer,bodyText)\r\n%% \r\n% The advantage of this is that we can now pass around all the information related \r\n% to a customer as a single variable. If their postal address is added to the \r\n% struct, it\u2019s automatically available for us to use in our |sendEmail| function.\r\n%% What\u2019s in a customer?\r\n% A disadvantage arises when a new developer (or you several weeks from now!) \r\n% looks at this function again. What exactly is _in_ the \u201ccustomer\u201d struct? Is \r\n% the field for their first name called \u201cFirstName\u201d or \u201cFirstname\u201d or \u201cfirstname\u201d? \r\n% \r\n% If you try to access a field that doesn\u2019t exist, you\u2019ll get an error, but \r\n% if you set a field that didn\u2019t previously exist, it will be automatically added \r\n% to the struct. Maybe you can work out the correct names from the existing code, \r\n% assuming it\u2019s not too long or complex. Otherwise, you\u2019ll have to run a test \r\n% (because <https:\/\/blogs.mathworks.com\/developer\/2021\/08\/31\/why-testing-is-worth-the-effort\/ \r\n% someone has written a test>, right?) and see what is provided to the function \r\n% at runtime. \r\n% \r\n% With a customer, we can at least take an educated guess as to the contents. \r\n% If a more generic name is adopted (\u201cdata\u201d, \u201cmetdadata\u201d, \u201cinfo\u201d), it can be impossible.\r\n% \r\n% This lack of clarity wastes developer time over and over again, and can cause \r\n% subtle bugs that are hard to track down.\r\n%% What\u2019s a valid customer?\r\n% To address this, we could define validation on the |customer| input: we want \r\n% to make sure that we have a scalar struct with the correct field names, that \r\n% the data types are correct, and that any other validation rules are met. For \r\n% example, that the email address is always of the format \u201c*@*.*\u201d . \r\n% \r\n% Managing this can be complex and laborious. If you\u2019re not careful, it leads \r\n% to scattered code that repeats the validation and that is difficult to read. \r\n% Furthermore, can we _guarantee_ that all such \u201ccustomer structs\u201d will always \r\n% be valid? No \u2013 it\u2019s possible for us, or another developer, to create an invalid \r\n% customer struct and we won\u2019t know about it until we run our validation again \r\n% or the code errors.\r\n% \r\n% This forms a second source of bugs \u2013 data that is not in the expected format. \r\n% Common issues include variables that are empty but shouldn\u2019t be, or a cellstr \r\n% that should be a string array.\r\n%% What do we need from a customer?\r\n% There are operations that we frequently need to perform on our customer struct. \r\n% For example, constructing the customer\u2019s full name from their first and last \r\n% name:\r\n%\r\n%    fullname = customer.FirstName + \" \" + customer.LastName;\r\n%% \r\n% Writing this code each time we need the full name either leads to code duplication \r\n% (and a high likelihood of inconsistency), or a function that\u2019s divorced from \r\n% its data and potentially hard to find.\r\n%% Define a class instead\r\n% Instead, we can <https:\/\/uk.mathworks.com\/help\/matlab\/matlab_oop\/create-a-simple-class.html \r\n% define a class> for our customer! Doing so will bring the following advantages:\r\n% \r\n% Functions that use the customer class only need one line of validation in \r\n% the arguments block \u2013 the required class. The validation line tells you exactly \r\n% what the input is, and you can immediately hit |Ctrl+D| to go to the class definition. \r\n% It forms a clear contract between the calling code and your class.\r\n% \r\n% The properties block tells you exactly what properties _all_ objects of that \r\n% class will have. The validation for each property makes explicit what each property \r\n% will contain, it can set default values, and it guarantees that all objects \r\n% of the class will be valid.\r\n% \r\n% Dependent properties can be added to give you derived information without \r\n% having to poke around the internals of the object (hello <https:\/\/blogs.mathworks.com\/developer\/2016\/08\/08\/han-solo-encapsulation\/ \r\n% encapsulation>!); <https:\/\/martinfowler.com\/bliki\/TellDontAsk.html tell the \r\n% object> what you want it to do, don\u2019t ask for the individual pieces of data. \r\n% Other functionality related to the class can be added as methods. \r\n%% Make your class work with arrays\r\n% Custom classes really begin to shine when you make them array compatible. \r\n% Rather than having _a_ customer or _an_ order, you can have an array of customers \r\n% or orders and perform operations on them in one go. This native array handling \r\n% is one of the unique features of MATLAB and removes the need for a \u201ccollection\u201d \r\n% object like you might have in C.\r\n% \r\n% An array-based method I almost always add is |table|. |table| transforms an \r\n% array of objects into a standard MATLAB <https:\/\/uk.mathworks.com\/help\/matlab\/ref\/table.html \r\n% table>. It allows you to easily see the entire contents of the object array \r\n% and perhaps to write the data into a <https:\/\/uk.mathworks.com\/help\/matlab\/ref\/uitable.html \r\n% uitable> for display or <https:\/\/uk.mathworks.com\/help\/matlab\/ref\/writetable.html \r\n% to a spreadsheet> for reporting purposes.\r\n% \r\n% So why go to all this trouble of creating a custom class just to turn it back \r\n% into a generic data type? The crucial difference now is that the table is _derived_ \r\n% from our custom class which handles all the validation and calculations; the \r\n% table is not the source of truth. \r\n%% Code example\r\n% Below is example code showing what a customer might look like when implemented \r\n% as a class in MATLAB:\r\n%% \r\n% * Property names are fixed, always present, and cannot be changed at runtime.\r\n% * Data types and sizes are fixed, and type conversion performed automatically \r\n% where possible (e.g. char to string).\r\n% * |Email| is validated whenever it is changed.\r\n% * The |FullName| dependent property gives calling code direct access to what \r\n% it actually wants.\r\n% * The |table| method allows us to easily visualise the contents of a customer \r\n% array and that data to be consumed outside of our application.\r\n%% \r\n% <include>Customer.m<\/include>\r\n%%\r\n% \r\n% Here\u2019s how we might use it:\r\n\r\nc(1) = Customer(\"Mitch\",\"Docker\",\"mitch@foo.com\")\r\nc(2) = Customer(\"Lachlan\",\"Morton\",\"lachlan@bah.com\");\r\nc(3) = Customer(\"Rigoberto\",\"Uran\",\"rigo@uran.com\");\r\ntable(c)\r\n%% \r\n% We can validate the inputs to our |sendEmail| function with a simple arguments \r\n% block:\r\n%% \r\n% <include>sendEmail.m<\/include>\r\n%% When should I define a custom class?\r\n% You may be wondering at what point you should go to the effort and formality \r\n% of creating custom classes. Much like making the decision to go from a script \r\n% to a function or a function to a class, it\u2019s when you hit the limits of what \r\n% your current implementation can do. If you find that:\r\n%% \r\n% * It\u2019s difficult to understand what\u2019s in your data structure.\r\n% * You have problems with validation.\r\n% * Code that\u2019s closely related to the data is duplicated, scattered, or inconsistent.\r\n%% \r\n% It\u2019s time to think about custom classes.\r\n##### SOURCE END ##### f3bb216fc38f43f48451dab42fbc494f\r\n-->","protected":false},"excerpt":{"rendered":"<p>Let&#8217;s send some emails!Imagine you write a function that sends an email to a customer. Your initial function call might look like this: ... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/developer\/2022\/03\/17\/using-custom-classes-to-convey-intent\/\">read more >><\/a><\/p>","protected":false},"author":178,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[6,16],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2782"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/users\/178"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/comments?post=2782"}],"version-history":[{"count":2,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2782\/revisions"}],"predecessor-version":[{"id":2788,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/posts\/2782\/revisions\/2788"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/media?parent=2782"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/categories?post=2782"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/developer\/wp-json\/wp\/v2\/tags?post=2782"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}