{"id":415770,"date":"2024-06-30T00:34:07","date_gmt":"2024-06-30T00:34:07","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=415770"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=415770","title":{"rendered":"<span>Modern COBOL: Package Tutorial<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>You will learn and create an application-level library in COBOL. You will structure the package, implement automatic tests, deploy on GitHub and enable Continuous Integration workflow. Finally, you will publish the package in the COBOL package registry.<\/p>\n<p><a name=\"habracut\"><\/a>  <\/p>\n<h2 id=\"preconditions\">Preconditions<\/h2>\n<p>  <\/p>\n<p>You have learned basic principles, methods and standards of COBOL. In this tutorial we\u2019ll use <strong>GnuCOBOL<\/strong> \u2014 a free COBOL compiler which implements a substantial part of the COBOL 85, COBOL 2002 and COBOL 2014 standards and X\/Open COBOL, as well as many extensions included in other COBOL compilers.<\/p>\n<p>  <\/p>\n<p>You have <strong>Docker<\/strong>, a command-line virtualization tool, installed.<\/p>\n<p>  <\/p>\n<p>You have <strong>NPM<\/strong>, a package manager for JavaScript programming language, installed.<\/p>\n<p>  <\/p>\n<p>You have <strong>Git<\/strong>, an open source distributed version control client, installed.<\/p>\n<p>  <\/p>\n<p>You have <strong>GitHub<\/strong> account for publishing of the package.<\/p>\n<p>  <\/p>\n<p>You may use any text editor you like, but I recommend <strong>Visual Studio Code<\/strong> (or its open-source version <strong>VSCodium<\/strong>) with COBOL-syntax extension <code>bitlang.cobol<\/code> installed.<br \/>  Package vs Library<\/p>\n<p>  <\/p>\n<p>Each programming language has standard set of functions or operators provided by default and included into installation package. In COBOL we call them Intrinsic functions. Intrinsics cover basic programming needs, but we\u2019ve used to extend default set by own functions every time writing something smarter than \u00b4Hello, world!\u00b4.<\/p>\n<p>  <\/p>\n<p>Gradually, custom functions form reusable COBOL libraries, Copybooks, for inclusion into other programs and services on-demand. Thanks to Version Control Systems, contributors are able to effectively cooperate and deliver the libraries to the programmers. The only problem was an integration with external source-code that might be casually written in other COBOL dialect, coding standard or approach. And package management is a solution here.<\/p>\n<p>  <\/p>\n<p>Similar to other application-level package managers, such as <strong>Yarn<\/strong> for JavaScript, <strong>Maven<\/strong> for Java, <strong>Packagist<\/strong> for PHP, <strong>NuGet<\/strong> for C# etc., in 2020 COBOL obtained its own public package manager that standardizes the way the contributors should treat the libraries \u2014 COBOLget. The tutorial explains how to create and publish your first COBOL package the modern way.<\/p>\n<p>  <\/p>\n<h2 id=\"specifications\">Specifications<\/h2>\n<p>  <\/p>\n<p>For financial applications we\u2019ll implement <code>banking<\/code> package which exposes single <code>iban-checksum<\/code> function \u2014 an <a href=\"https:\/\/en.wikipedia.org\/wiki\/International_Bank_Account_Number\" rel=\"nofollow\">IBAN<\/a> validator. The function accepts alphanumeric argument and returns numeric value <code>1<\/code> in case of success. The algorithm is as follows:<\/p>\n<p>  <\/p>\n<ul>\n<li>Check IBAN length.<\/li>\n<li>Move the first <em>4<\/em> characters to the end.<\/li>\n<li>Replace each letter with two digits, where <em>A = 10, B = 11, \u2026, Z = 35<\/em>.<\/li>\n<li>Compute the remainder by <em>MOD97<\/em> intrinsic function. If the remainder is <em>1<\/em>, the checksum is valid.<\/li>\n<\/ul>\n<p>  <\/p>\n<h2 id=\"structuring\">Structuring<\/h2>\n<p>  <\/p>\n<p>Please create new GitHub repository <code>demo-banking<\/code> and copy <a href=\"https:\/\/github.com\/OlegKunitsyn\/gnucobol-examples\/tree\/master\/package\" rel=\"nofollow\">template of the package<\/a> to your local copy of the repository. Here\u2019s a structure of the package:<\/p>\n<p>  <\/p>\n<pre><code class=\"plaintext\">\u251c\u2500\u2500 Dockerfile \u251c\u2500\u2500 .github \u2502   \u2514\u2500\u2500 workflows \u2502       \u2514\u2500\u2500 docker-image.yml \u251c\u2500\u2500 .gitignore \u251c\u2500\u2500 modules.json \u251c\u2500\u2500 modules-lock.json \u251c\u2500\u2500 README.md \u251c\u2500\u2500 src \u2502   \u2514\u2500\u2500 banking.cbl \u2514\u2500\u2500 tests     \u2514\u2500\u2500 banking-test.cbl<\/code><\/pre>\n<p>  <\/p>\n<p>For COBOLget packages <em>Dockerfile<\/em>, <em>README.md<\/em>, <em>.gitignore<\/em> and <em>.workflows<\/em> are optional, but our library follows <strong>Continuous Integration<\/strong> practices, where each modification of the source-code is getting tested on the repository. On each push or pull request GitHub will trigger <code>docker-ci<\/code> workflow. In its turn, Docker will download GnuCOBOL image <code>gnucobol2.2<\/code>, install COBOLget dependencies from <code>modules-lock.json<\/code> and will execute GCBLUnit tests in <code>banking-test.cbl<\/code>.<\/p>\n<p>  <\/p>\n<p>The file <code>modules.json<\/code> is a <strong>Manifest<\/strong> of the package which describes the library and its dependencies:<\/p>\n<p>  <\/p>\n<pre><code class=\"json\">{   \"name\": \"demo-banking-FIXME\",   \"description\": \"Demo banking package\",   \"modules\": [     \"src\/banking.cbl\"   ],   \"dialect\": \"gnucobol\",   \"licenses\": [     \"MIT\"   ],   \"authors\": [     \"FIXME\"   ],   \"dependencies\": {},   \"dependencies-debug\": {     \"gcblunit\": \"*\"   } }<\/code><\/pre>\n<p>  <\/p>\n<p>The properties are speaking enough and similar to other package managers. Our package does not use any dependencies, but requires <code>gcblunit<\/code> package at any version (by default, the latest available) for development and debugging purposes. Property <code>modules<\/code> must contain COBOL modules (programs and functions) for inclusion as a Copybook. Full schema of the Manifest you may find on <a href=\"https:\/\/cobolget.com\/schema.json\" rel=\"nofollow\">https:\/\/cobolget.com\/schema.json<\/a>.<\/p>\n<p>  <\/p>\n<p>Let\u2019s install <code>cobolget<\/code> command-line tool and validate our package:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ npm install -g cobolget $ cobolget validate An error occurred: Error: \"demo-banking-FIXME\" does not match to ^[a-z0-9\\-]+$<\/code><\/pre>\n<p>  <\/p>\n<p>Oops! Please replace <em>FIXME<\/em> with your GitHub username in <em>README.md<\/em>, as well as in the Manifest in lower-case, making the package valid and unique in the COBOLget registry. Don\u2019t forget to replace <em>FIXME<\/em> in the command below as well:<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ cobolget validate Manifest modules.json is valid. $ cobolget list demo-banking-FIXME No matching results.<\/code><\/pre>\n<p>  <\/p>\n<p>Well done! The structure of the package is finished. We\u2019ll test our library in the next step.<\/p>\n<p>  <\/p>\n<h2 id=\"testing\">Testing<\/h2>\n<p>  <\/p>\n<p>The file <code>banking-test.cbl<\/code> has 8 GCBLUnit assertions that expect <em>\u201c1\u201d<\/em> returned by <code>iban-checksum<\/code> function. Let\u2019s execute <code>docker-ci<\/code> workflow locally, an one-liner<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ docker build --tag package .<\/code><\/pre>\n<p>  <\/p>\n<p>As you can see, creation of the Docker image fails on testing phase.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">....FFFF  Time: 00:00:00 There was 0000000004 failure(s): F banking-test #05 assert-equals    1 &lt;> 0                                F banking-test #06 assert-equals    1 &lt;> 0                                F banking-test #07 assert-equals    1 &lt;> 0                                F banking-test #08 assert-equals    1 &lt;> 0  FAILURES! Tests: 0000000001, Skipped: 0000000000 Assertions: 0000000008, Failures: 0000000004, Exceptions: 0000000000 The command '\/bin\/sh -c cobc -x -debug modules\/gcblunit\/gcblunit.cbl tests\/* --job='banking-test'' returned a non-zero code: 1<\/code><\/pre>\n<p>  <\/p>\n<p>The last 4 of 8 assertions returned <em>\u201c0\u201d<\/em> instead of expected <em>\u201c1\u201d<\/em>. Definitely, it\u2019s a <strong>false negative<\/strong> result because these numbers have been carefully copied from Wikipedia. \ud83d\ude42 You may remove inner spaces and try again, but I suggest you to improve <code>iban-checksum<\/code> function instead. Spaces are generally acceptable in IBAN and must pass the validation. The best implementation will be included into <em>core<\/em> COBOLget package under your name. Nevertheless, you may commit and push the package on GitHub and proceed to the next step.<\/p>\n<p>  <\/p>\n<h2 id=\"publishing\">Publishing<\/h2>\n<p>  <\/p>\n<p>Please \u201crelease\u201d your package on GitHub by attaching a version tag e.g. <code>1.2.3<\/code> to the commit. COBOLget implements <a href=\"https:\/\/semver.org\/\" rel=\"nofollow\">SemVer<\/a> versioning standard, any other tags will be skipped during the import. Now you can import your package into <a href=\"https:\/\/cobolget.com\/\" rel=\"nofollow\">COBOLget Registry<\/a> by using <code>index<\/code> command, from the command-line or on the website.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ cobolget index -h Usage: index [options] &lt;name|url>  Import or update the package in the registry  Options:   -t, --token &lt;token> Repository token for private package   -o, --organization &lt;organization> Organization name for private package   -h, --help output usage information<\/code><\/pre>\n<p>  <\/p>\n<p>Newborn packages we index by URL of the repository. Further releases we can index by the name.<\/p>\n<p>  <\/p>\n<pre><code class=\"bash\">$ cobolget index https:\/\/github.com\/FIXME\/demo-banking Package 'demo-banking-FIXME' has been indexed in the registry.<\/code><\/pre>\n<p>  <\/p>\n<p>Your first COBOL package is published on cobolget.com and ready for integration into applications and <a href=\"https:\/\/habr.com\/en\/post\/512676\/\">microservices<\/a>.<\/p>\n<p>  <\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>  <\/p>\n<p>You have created and successfully published your application-level COBOL library in COBOLget format by using Git, Docker, Unit-Testing and Continuous Integration practices. 60-years old COBOL fits modern software engineering.<\/p>\n<p>  <\/p>\n<p>Are you Wikipedia editor? Please help publish missing <a href=\"https:\/\/en.wikipedia.org\/wiki\/COBOLget_(software)\" rel=\"nofollow\">article<\/a> from the <a href=\"https:\/\/en.wikipedia.org\/wiki\/User:Cobollero\/sandbox\" rel=\"nofollow\">sandbox<\/a>.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/515112\/\"> https:\/\/habr.com\/ru\/articles\/515112\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-1\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>You will learn and create an application-level library in COBOL. You will structure the package, implement automatic tests, deploy on GitHub and enable Continuous Integration workflow. Finally, you will publish the package in the COBOL package registry.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-415770","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/415770","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=415770"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/415770\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=415770"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=415770"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=415770"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}