<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-13000143</id><updated>2026-04-11T15:18:02.605-07:00</updated><category term="Oracle"/><category term="UKOUG"/><category term="SQL"/><category term="openworld"/><category term="Conference"/><category term="Design"/><category term="openworld07"/><category term="PL/SQL"/><category term="Community"/><category term="UKOUG2007"/><category term="Humour"/><category term="Blog"/><category term="software engineering"/><category term="OTN forum"/><category term="UKOUG2006"/><category term="programming"/><category term="spamtard"/><category term="DESIG"/><category term="Presenting"/><category term="books"/><category term="careers"/><category term="WTF"/><category term="performance"/><category term="principles"/><category term="Film"/><category term="openworld09"/><category term="process"/><category term="standards"/><category term="Art"/><category term="Data Model"/><category term="Development"/><category term="Larry Ellison"/><category term="Schema"/><category term="Sun"/><category term="UKOUG2008"/><category term="interfaces"/><category term="software architecture"/><category term="CMG"/><category term="Database"/><category term="NULL"/><category term="SF"/><category term="SQL TYPE"/><category term="chip"/><category term="history"/><category term="licencing"/><category term="project mgmt"/><category term="weather"/><category term="Big Data"/><category term="David Bowie"/><category term="Hero"/><category term="Linux"/><category term="Oracle. PL/SQL"/><category term="SIG"/><category term="Security"/><category term="UKOUG2016"/><category term="architecture"/><category term="best practice"/><category term="computer"/><category term="error"/><category term="future"/><category term="logica"/><category term="meetup"/><category term="music"/><category term="neologism"/><category term="10g"/><category term="ACE"/><category term="Analytics"/><category term="BCS"/><category term="Browser"/><category term="Career"/><category term="Curry"/><category term="DB2"/><category term="DUAL"/><category term="Film Review"/><category term="Geek culture"/><category term="I Ching"/><category term="Integration"/><category term="Java"/><category term="MSSQL"/><category term="MySQL"/><category term="New Yorker"/><category term="NoSQL"/><category term="NorTech18"/><category term="Office life"/><category term="Partitioning"/><category term="PostgreSQL"/><category term="Requirements"/><category term="SOA"/><category term="StackOverflow"/><category term="Survey"/><category term="Trigger"/><category term="Ubuntu"/><category term="Web"/><category term="acquistions"/><category term="beer"/><category term="blog rolling"/><category term="data"/><category term="exceptions"/><category term="fonts"/><category term="freelance"/><category term="interest"/><category term="law"/><category term="lock"/><category term="logging"/><category term="metadata"/><category term="openness"/><category term="parallel"/><category term="patch"/><category term="performance oracle"/><category term="planning"/><category term="quizzes"/><category term="recruitment"/><category term="solid"/><category term="storage"/><category term="t-shirt"/><category term="team building"/><category term="technology"/><category term="testing"/><category term="work"/><category term="writing"/><title type='text'>Radio Free Tooting</title><subtitle type='html'>Notes from the Tooting Bec Underground</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default?alt=atom'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default?alt=atom&amp;start-index=26&amp;max-results=25'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>308</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-13000143.post-6556781084039104092</id><published>2020-09-18T06:34:00.000-07:00</published><updated>2020-09-18T06:34:14.388-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="interfaces"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><title type='text'>The use and misuse of %TYPE and %ROWTYPE attributes in PL/SQL APIs</title><content type='html'>PL/SQL provides two attributes which allow us to declare a data structure with its datatype derived from a database table or a previously declared variable.
&lt;br&gt;&lt;p&gt;
We can use &lt;code&gt;%type&lt;/code&gt; attribute for defining a constant, a variable, a collection element, record field or PL/SQL program parameters. While we can reference a previously declared variable, the most common use case is to tie the declaration to a table column. The following snippet declares a variable with the same datatype and characteristics (length, scale, precision) as the SAL column of the EMP table.
&lt;pre&gt;
l_salary emp.sal%type;
&lt;/pre&gt;
We can use the &lt;code&gt;%rowtype&lt;/code&gt; attribute to declare a record variable which matches the projection of a database table or view, or a cursor variable. The following snippet declares a variable with the same projection as the preceeding cursor.
&lt;pre&gt;
cursor get_emp_dets is
  select emp.empno
         , emp.ename
         , emp.sal
         , dept.dname
  from   emp
  inner join dept on dept,deptno = emp.deptno;        
l_emp_dets get_emp_dets%rowtype;
&lt;/pre&gt;
Using these attributes is considered good practice. PL/SQL development standards will often mandate their use. They deliver these benefits:&lt;br&gt;
&lt;ol&gt;&lt;li&gt;self-documenting code: if we see a variable with a definition which references &lt;code&gt;emp.sal%type&lt;/code&gt; we can be reasonably confident this variable will be used to store data from the SALARY column of the EMP table.
&lt;li&gt;datatype conformance: if we change the scale or precision of the the SALARY column of the EMP table all variables which use the &lt;code&gt;%type&lt;/code&gt; attribute will pick up the change automatically. If we add a new column to the EMP table, all variables defined with the &lt;code&gt;%rowtype&lt;/code&gt; attribute will be able to handle that column without us needing to change those programs.
&lt;/ol&gt;
That last point comes with an amber warning: the automatic conformance only works when the &lt;code&gt;%rowtype&lt;/code&gt; variable is populated by  SELECT * FROM queries. If we are using an explicit projection with named columns then we have now broken our code and we need to fix it. More generally, this silent propagation of changes to our data structures means we need to pay more attention to impact analysis. Is it right that we can just change a column&#39;s datatype or amend a table&#39;s projection without changing the code which depends on them? Maybe it&#39;s okay, maybe not. By shielding us from the immediate impact of broken code, using these attributes also withholds the necessity to revisit our programs: so we have to remember to do it. 
&lt;br&gt;&lt;p&gt;
Overall I think the benefits listed above outweigh the risks, and I think we should always use these attributes whenever it is appropriate, &lt;i&gt;for the definition of local variables and constants&lt;/i&gt;. However, complications arise if we use them to declare PL/SQL program parameters, specifically for procedures in package specs and standalone program units. It&#39;s not so bad if we&#39;re writing an internal API but it becomes a proper headache when we are dealing with a public API, one which will be called by programs owned by another user, one whose developers are in another team or outside our organisation, or even using Java, dotNet or whatever. So why is the use of these attributes so bad for those people?
&lt;br&gt;&lt;p&gt;
&lt;ol&gt;&lt;li&gt;obfuscated code: these attributes are only self-documenting when we have a familiarity with the underlying schema, or have easy access to it. This will frequently not be the case for developers in other teams (or outside the organisation) who need to call our API. They may be able to guess at the datatype of SALARY or HIREDATE, but they really shouldn&#39;t have to. And, of course, a reference to &lt;code&gt;emp%rowtype&lt;/code&gt; is about as unhelpful as it could be. Particularly when we consider ...
&lt;li&gt;loss of encapsulation: one purpose of an API is to shield consumers of our application from the gnarly details of its implementation. However, the use of &lt;code&gt;%type&lt;/code&gt; and &lt;code&gt;%rowtype&lt;/code&gt; is actually exposing those details. Furthermore, a calling program cannot define their own variables using these attributes &lt;i&gt;unless we grant them SELECT on the tables&lt;/i&gt;. Otherwise the declaration will hurl PLS-00201. This is particularly problematic for handling &lt;code&gt;%rowtype&lt;/code&gt;, because we need to define a record variable which matches the row structure.
&lt;li&gt;breaking the contract: an interface is an agreement between the provider and the calling program. The API defines input criteria and in return guarantees outcomes. It forms a contract, which allows the consumer to write code against stable definitions. Automatically propagating  changes in the underlying data structures to parameter definitions creates unstable dependencies. It is not simply that the use of &lt;code&gt;%type&lt;/code&gt; and &lt;code&gt;%rowtype&lt;/code&gt; attributes will cause the interface to change automatically, the issue is that there is no mechanism for signalling the change to an API&#39;s consumers. Interfaces demand stable dependencies: we must manage any changes to our schema in a way which ideally allows the consumers to continue to use the interface without needing to change their code, but at the very least tells them that the interface has changed. 
&lt;/ol&gt;  
&lt;h2&gt;Defining parameters for public APIs&lt;/h2&gt;
The simplest solution is to use PL/SQL datatypes in procedural signatures. These seem straightforward. Anybody can look at this function and understand that input parameter is numeric and the returned value is a string.
&lt;pre&gt;
function get_dept_manager (p_deptno in number) return varchar2;
&lt;/pre&gt;
So clear but not safe. How long is the returned string? The calling program needs to know, so it can define an appropriately sized variable to receive it. Likewise, in this call, how long is can a message be?
&lt;pre&gt;
procedure log_message (p_text in varchar2);
&lt;/pre&gt;     
Notoriously we cannot specify length, scale or precision for PL/SQL parameters. But the calling code and the called code will write values to concretely defined types. The interface needs to communicate those definitions. Fortunately PL/SQL offers a solution: subtypes. Here we have a substype which explicitly defines the datatype to be used for passing messages: 
&lt;pre&gt;
subtype st_message_text is varchar2(256);

procedure log_message (p_text in st_message_text);
&lt;/pre&gt;
Now the calling program knows the maximum permitted length of a message and can trim its value accordingly. (Incidentally, the parameter is still not constrained in the called program so we can pass a larger value to the &lt;code&gt;log_message()&lt;/code&gt; procedure: the declared length is only enforced when we assign the parameter to something concrete such as a local variable.) 
&lt;br&gt;&lt;p&gt;
We can replace &lt;code&gt;%rowtype&lt;/code&gt; definitions with explicit RECORD defintions. So a function which retrieves the employee records for a department will look something like this:
&lt;pre&gt;
subtype st_deptno is number(2,0);

type r_emp is record(
  empno          number(4,0),
  ename          varchar2(10),
  job            varchar2(9),
  mgr            number(4,0),
  hiredate       date
  sal            number(7,2),
  comm           number(7,2),
  deptno         st_deptno
);
  
type t_emp is table of r_emp;  

function get_dept_employees (p_deptno in st_deptno) return t_emp;
&lt;/pre&gt;
We do this for all our public functions.
&lt;pre&gt;
subtype st_manager_name is varchar2(30);

function get_dept_manager (p_deptno in st_deptno) return st_manager_name;
&lt;/pre&gt;
Now the API clearly documents the datatypes which calling programs need to pass and which they will receive as output. Crucially, this approach offers stability: the datatype of a parameter cannot be changed invisibly, as any change must be implemented in a new version of the publicly available package specification. Inevitably this imposes a brake on our ability to change the API but we ought not to be changing public APIs frequently. Any such change should arise from either new knowledge about the requirements or a bug in the data model. Wherever possible we should try to handle bugs internally within the schema. But if we have to alter the signature of a procedure we need to communicate the change to our consumers as far ahead of time as possible. Ideally we should shield them from the need to change their code at all. One way to achieve that is &lt;a href=&quot;https://docs.oracle.com/en/database/oracle/oracle-database/19/adfns/editions.html#GUID-3C543B31-9BA6-421D-9791-D85866185052&quot; alt=&quot;Oracle 19c Database Development Guide&quot;&gt;Edition-Based Redefinition&lt;/a&gt;. Other ways would be to deploy the change with overloaded procedures or even using a different procedure name, and deprecate the old procedure. Occasionally we might have no choice but to apply the change and break the API: sometimes with public interfaces the best we can do is try to annoy the fewest number of people.
&lt;h2&gt;Transitioning from a private to a public interface&lt;/h2&gt;    
There is a difference between internal and public packages. When we have procedures which are intended for internal usage (i.e. only called by other programs in the same schema) we can define their parameters with &lt;code&gt;%type&lt;/code&gt; and &lt;code&gt;%rowtype&lt;/code&gt; attributes. We have access and - it is to be hoped! - familiarity with the schema&#39;s objects, so the datatype anchoring supports safer coding. But what happens when we have a package which we wrote as an internal package but now we need to expose its functionality to a wider audience? Should we re-write the spec to use subtypes instead?
&lt;br&gt;&lt;p&gt;
No. The correct thing to do is to write a wrapper package which acts as a facade over the internal one, and grant EXECUTE privileges on the wrapper. The wrapper package will obviously have the requisite subtype definitions in the spec, and procedures declared with those subtypes. The package body will likely consist of nothing more than those procedures, which simply call their equivalents in the internal package. There may be some affordances for translating data structures, such as populating a table &lt;code&gt;%rowtype&lt;/code&gt; variable from the public &lt;code&gt;record&lt;/code&gt; type, but those will usually be necessary only for the purposes of documentation (&lt;i&gt;this publicly defined subtype maps to this internally defined table column&lt;/i&gt;). There is an obvious overhead to writing another package, especially one which is really just a pass-through to the real functionality, but there are clear benefits which justify the overhead:
&lt;ul&gt;&lt;li&gt;Stability. Not re-writing an existing package is always a good thing. Even if we are mechanically just replacing one set of datatype definitions with a different set which have the same characteristics we are still changing the core system, and that&#39;s a chunk of regression testing we&#39;ve just added to the task.
&lt;li&gt;Least privilege escalation. Even if the internal package has been written with a firm eye on the SOLID principles, the chances are it contains more functionality than we need to expose to other consumers. Writing a wrapper package gives us the opportunity to grant access to only the required procedures.
&lt;li&gt;Composition. It is also likely that the internal package doesn&#39;t have the exact procedure the other team needs. Perhaps there are actually two procedures they need to call, or there&#39;s one procedure but it has some confusing internal flags in its signature. Instead of violating &lt;a href=&quot;https://radiofreetooting.blogspot.com/2017/12/data-access-layer-vs-table-apis.html&quot; alt=&quot;Data Access Layer vs Table APIs &quot;&gt;the Law of Demeter&lt;/a&gt; we can define one simple procedure in the wrapper package spec and handle the internal complexity in the body.
&lt;li&gt;Future proofing. Writing a wrapper package gives us an affordance where we can handle subsequent changes in the internal data model or functionality without affecting other consumers. By definition a violation of &lt;a href=&quot;https://www.martinfowler.com/bliki/Yagni.html&quot; alt=&quot;Martin Fowler on YAGNI&quot;&gt;YAGNI&lt;/a&gt;, but as it&#39;s not the main reason why we&#39;re doing this I&#39;m allowing this as a benefit.    
&lt;/ul&gt;
&lt;h2&gt;Design is always a trade off&lt;/h2&gt;
The use of these attributes is an example of the nuances which Coding Standards often lack. In many situations their use is good practice, and we should employ them in those cases. But we also need to know when their use is a bad practice, and why, so we can do something better instead. &lt;br&gt;&lt;p&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/6556781084039104092/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/6556781084039104092' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/6556781084039104092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/6556781084039104092'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2020/09/the-use-and-misuse-of-type-and-rowtype.html' title='The use and misuse of &lt;code&gt;%TYPE&lt;/code&gt; and &lt;code&gt;%ROWTYPE&lt;/code&gt; attributes in PL/SQL APIs'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-8862231969602417156</id><published>2020-09-09T08:13:00.002-07:00</published><updated>2020-09-09T08:13:52.995-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Humour"/><category scheme="http://www.blogger.com/atom/ns#" term="project mgmt"/><category scheme="http://www.blogger.com/atom/ns#" term="team building"/><title type='text'>Ten character classes your project team needs</title><content type='html'>A dungeon-crawling party requires a good mix of character classes to be successful. If everyone is a wizard there&#39;s nobody who can fight off the orc warband. Similarly, a software development team needs a range of character traits and aspects to successfully deliver working software which meets the project&#39;s goals. Here&#39;s my take. 
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Scavenger&lt;/h2&gt;
The Scavenger understands the importance of not re-inventing the wheel. To this end they acquire an encyclopaedic understanding of our languages&#39; built-in libraries, the existing features of our system and other systems in the wider organisation, and open-source libraries.
&lt;br&gt;&lt;p&gt;
Unless given a precise list of the project&#39;s wants a Scavenger will become a Mutant Renegade, scouring the post-atomic wasteland for useless relics, which are broken or undocumented or both. &lt;br&gt;&lt;p&gt;
&lt;b&gt;Aspect:&lt;/b&gt; &quot;Here&#39;s one we made earlier&quot;&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Focused laziness, Unfocused research, GitHub&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Rat King&lt;/h2&gt;
The Rat King understands that software development is a communal task. Consequently they work to forge a collection of disparate individuals into a team. Their remit includes facilitating meetings and arranging after-work socials. Despite their fearsome appearance and collectivist instincts the Rat King is extremely sensitive to what each person brings to the party, and strives to ensure that introverts and teetotallers are included without feeling pressurized. 
&lt;br&gt;&lt;p&gt;
Unless met with a smidgeon of friendly scepticism a Rat King will become a Facebook. 
&lt;br&gt;&lt;p&gt;
&lt;b&gt;Aspect:&lt;/b&gt; &quot;We must hang together or we will surely hang separately&quot;&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Teamwork, Communications, Contacts&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Paladin&lt;/h2&gt;
The Paladin is the defender of the project but is also committed to the ideal of a project which is worth defending. They ensure everybody follows best practice, adheres to coding standards and observes the agile ceremonies. 
&lt;br&gt;&lt;p&gt;
Unless there&#39;s a Rogue to balance them a Paladin will become a Grand Inquisitor (although maybe without the thumbscrews). 
&lt;br&gt;&lt;p&gt;
&lt;b&gt;Aspect:&lt;/b&gt; &quot;Just do it right&quot;&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Rigour, Weird inner light&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Rogue&lt;/h2&gt;
The Rogue is pragmatic where the Paladin is dogmatic. They have a swashbuckling approach to getting things done. They understand the concept of technical debt, they just tip the trade-off toward delivering stuff over following the rules. Very fond of observing that there&#39;s no such thing as &quot;best practice&quot;. 
&lt;br&gt;&lt;p&gt;
Unless kept in line a Rogue will become a Cowboy. Yee-hah!
&lt;br&gt;&lt;p&gt;
&lt;b&gt;Aspect:&lt;/b&gt; &quot;Let&#39;s do the show right here&quot;&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Resourcefulness, Acute bullshit detector, Cynefin&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Mad Scientist &lt;/h2&gt;
The Mad Scientist has a deep technical understanding of software development, both practice and theory. They are obsessed with innovative and extremely clever solutions to business problems.
&lt;br&gt;&lt;p&gt;
Unless your business problem actually requires an extremely clever solution a Mad Scientist will become an Evil Supervillain, who will derail the project (but, to be fair, will not destroy the entire planet. Probably).&lt;br&gt;&lt;p&gt; 
&lt;b&gt;Aspect:&lt;/b&gt; &quot;My monster lives!&quot; &lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Single-mindedness, Visionary&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Lab Assistant&lt;/h2&gt;
The Lab Assistant is vital to delivering the work of a Mad Scientist. They document APIs on wiki pages, they write build scripts and unit tests, they productionize the PoC code. In short, they undertake all the tedious essential tasks which would distract a Mad Scientist from their creation.  
&lt;br&gt;&lt;p&gt;
A Lab Assistant to an Evil Supervillain is still a Lab Assistant, but the wiki pages are half-complete, the unit tests don&#39;t run and the code isn&#39;t fit to be checked into source control.&lt;br&gt;&lt;p&gt;
&lt;b&gt;Aspect:&lt;/b&gt; &quot;Here is the brain you wanted&quot;&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Flexibility, Service to the higher cause&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Major-domo&lt;/h2&gt;
The Major-domo helps the project run smoothly by taking care of all the little things everybody else forgets. They clean the whiteboard before a meeting starts, they bring Sharpies and Post-It notes to the retrospective, they write Jiras for the stories we just agreed we needed and they circulate minutes after decision-making meetings.
&lt;br&gt;&lt;p&gt;
Unless other people occasionally do some of these tasks a Major-domo will become a Resentful Skivvy. 
&lt;br&gt;&lt;p&gt;  
&lt;b&gt;Aspect:&lt;/b&gt; &quot;I&#39;ll add that to my To-Do list&quot;&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Well-stocked stationary cupboard, Scrivener&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Court Jester&lt;/h2&gt;
The Court Jester says out loud the things everybody else is thinking. They aren&#39;t afraid to appear ridiculous in order to make a point. Their role is to speak truth to power.
&lt;br&gt;&lt;p&gt;
If they go too far a Jester becomes an Angry Ranter, ignored and shunned by everybody. 
&lt;br&gt;&lt;p&gt;
&lt;b&gt;Aspect:&lt;/b&gt; &quot;The true fool stays silent in the face of foolishness&quot;&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Humour, Insight, Lack of inhibition&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Bounty Hunter&lt;/h2&gt;
The Bounty Hunter lives for finding and fixing bugs. They are never happier when writing test cases to reproduce a bug or stepping through lines of code in debug mode. They understand that fixing production code is more important than delivering a new feature.
&lt;br&gt;&lt;p&gt;
Unless kept on a tight leash a Bounty Hunter will become a Mindless Delver or a Tinkerer.&lt;br&gt;&lt;p&gt;
&lt;b&gt;Aspect:&lt;/b&gt; “To defeat the bug, we must understand the bug”&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Sense of purpose, Perseverance, Debugging&lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Druid&lt;/h2&gt;
The Druid has an understanding of ecosystem beyond our project&#39;s bounded context. They know what the business seeks to achieve and how our project furthers those goals. They also know about other projects in the organisation, and work to ensure our project integrates with them harmoniously. 
&lt;br&gt;&lt;p&gt;
Unless given a clear sense of our project&#39;s priorities and direction a Druid is still a Druid, just servicing the needs of other projects.&lt;br&gt;&lt;p&gt;
&lt;b&gt;Aspect:&lt;/b&gt; &quot;Listen to the trees, dude&quot;&lt;br&gt;
&lt;b&gt;Traits:&lt;/b&gt; Awareness, Empathy, Balance &lt;br&gt;
&lt;br&gt;&lt;p&gt;
&lt;h1&gt;Multi-faceted characters&lt;/h1&gt;
Obviously these aren&#39;t main character classes. A project team comprises base classes such as Developers, Testers, Analysts, Architects, heck maybe even a Project Manager. What I list here are ancillary classes, which modify a base class. An Architect, a Developer, an Analyst or a Project Manager can benefit from having a touch of the Druid about them. Any Developer should spend some time being a Bounty Hunter or Scavenger. Different circumstances demand different class behaviours. When there&#39;s a major outage in Production we need Rogues to fix it, not Paladins muttering about process and sign-off. But after Production is back it is the Paladins who make sure the problem and its resolution are properly documented, and appropriate preventative measures put in place. Most people on the team will flow through several of these class behaviours, even over the course a single sprint. 
&lt;br&gt;&lt;p&gt;
When we&#39;re forming a new team to deliver some piece of software we focus on the hard skills. the main character classes. We need this many Developers, this many Analysts, a UX expert, an SEO specialist, and so forth. These are the easy things to define. But the success of the project will in large part depend on the soft skills and temperaments of the individuals in the team. This is a lot harder to measure. It&#39;s why personality tests like Myers-Briggs and Insights exist: some people think they&#39;re hokum but they provide a framework for assessing the make-up of a team in an age when we&#39;re uncomfortable casting horoscopes or taking auguries from the liver of a freshly-slaughtered goose. Using RPG character classes as  metaphors for desirable behaviours has the advantage of jokiness. There is a categorical absence of pyschological research underpinning this article. Also it doesn&#39;t require us to obtain live waterfowl.   
&lt;br&gt;&lt;p&gt;
One last thing. The next time you find yourself at a retrospective with no marker pens and nothing to write on, look around for a Major-domo. And if you can&#39;t spot one why not appoint yourself to the role?   
&lt;h1&gt;Epilogue&lt;/h1&gt;  
That final paragraph makes me sad for the times when retrospectives happened in a room with other people, with a whiteboard covered in post-It notes. Let&#39;s hope we can do them like that again.
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/8862231969602417156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/8862231969602417156' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/8862231969602417156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/8862231969602417156'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2020/09/ten-character-classes-your-project-team.html' title='Ten character classes your project team needs'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-2967606424810879458</id><published>2020-08-25T07:10:00.001-07:00</published><updated>2020-08-25T07:10:45.174-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="best practice"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="programming"/><title type='text'>How PL/SQL Development Standards work</title><content type='html'>I have been gigging at a place which has documented PL/SQL Development Standards. This is not so unusual: most Oracle shops have such a document. What makes it unusual is that they enforce the standards. With code reviews. And I mean properly enforce: programs fail QA for egregious breaches of the standards or a sufficient accumulation of minor breaches. This is less common than it ought to be.
&lt;br&gt;&lt;p&gt;
Many coders are sceptical about development standards; I have been in the past. Standards generally focus on things which are easy to standardise (indentation, case, naming conventions) rather functional correctness or design principles. They frequently codify arbitrary or outdated practices (mandating explicit cursors is a particular bugbear of mine). They either go into so much detail that they are unreadably long (and dull) or are so sketchy that they operate as easy-to-ignore guidelines. But I think many experienced developers&#39; objections boil down to: &lt;i&gt;I don&#39;t like being told how to write my code; my style is the best style; my code is clean, clear and readable&lt;/i&gt;. 
&lt;br&gt;&lt;p&gt;  
The catch is, readability is not simply a function of personal style: it emerges from consistency &lt;b&gt;across the entire codebase&lt;/b&gt;. Just because I find my personal coding style clear doesn&#39;t mean everbody else will. At the very least a colleague reading my program will have to invest time in understanding how I name my variables, how I use table aliases, and a dozen other things, none of them important individually but all together adding friction to the crucial task of understanding how a program works (or does not work).
&lt;br&gt;&lt;p&gt;
This particular set of standards certainly had a lot to say about layout. Many strictures fitted with my natural coding style (all lower case, one column per line in a SQL projection, comma before the column name rather than after it). Others were rather tiresome: the rules for clause alignment entail a lot of spacing and backspacing to ensure elements line up.  There are a few strictures I actively disagree with (notably mandatory use of SQL-89 syntax i.e. impicit joins). But here&#39;s the rub: I didn&#39;t get to pick and choose which of the standards I followed. I just had to knuckle down and follow them all. Because the discipline of the code review meant my programs failed QA when I hadn&#39;t applied the standards.
&lt;br&gt;&lt;p&gt;
There&#39;s more to consistency than just layout and naming conventions. There&#39;s also functional consistency: use of SQL and PL/SQL idioms, how to organise programs within a package, and so forth. Too many things to cover in a single document. But again, code reviews enforce standardisation of these aspects, by applying undocumented conventions with the same rigour as documented standards.  A couple of times I tripped over such an undocumented convention and it didn&#39;t feel fair: my code failed the review because I wrote something which was wrong even though not explicitly covered by the standards. One of these times it was something awry in the layout. &quot;That&#39;s wrong&quot;, the reviewer said. It was a difference I hadn&#39;t even noticed, and probably you wouldn&#39;t have noticed either, and even if I had have noticed it I wouldn&#39;t have thought it was &lt;i&gt;wrong&lt;/i&gt;. But it was different from what everybody else was doing. That made it wrong. 
&lt;br&gt;&lt;p&gt;  
Everybody undertakes code reviews and everybody&#39;s code is reviewed. Thus code reviews shape the codebase, by enforcing documented standards and undocumented conventions. As a result this is the most readable codebase I have ever worked on. It&#39;s almost impossible to tell who wrote any given program, because all programs look the same. It&#39;s easy to reason about a piece of code because it follows rigorous naming conventions and consistent architectural principles. The code is habitable. A colleague can read a program I wrote and feel comfortable doing so. The layout, the naming conventions, the consistent selection of one approach in situations where PL/SQL offers more than one way of doing something, all these factors mean my program looks just like the program anybody else would have written. So the reader is freer to understand what the program actually does and how it works. Standardisation reduces friction. 
&lt;br&gt;&lt;p&gt;
It is a virtuous circle. Code reviews enforce a consistent programming style, which eliminates trivial (i.e. non-functional) differences in the program. In turn this makes the program easier to review: all the programs look basically the same which highlights the things which need to be different, the business logic and the data structures.    
&lt;br&gt;&lt;p&gt;
&lt;h2&gt;Readability is a feature&lt;/h2&gt;
Readility is a feature. It&#39;s a feature our code must have. We all know readability makes code easier to maintain, easier to re-use, easier to debug. Yet still many developers bridle at the suggestion that their PL/SQL must look like everybody else&#39;s PL/SQL. I get this. It&#39;s not that I think the way I write PL/SQL is intrinsically correct, it just looks the way I have evolved to write it over the years.  A new set of coding standards, rigorously applied, disrupts my flow. I must slow down to correct the variable names or fix the layout. It&#39;s tedious. 
&lt;br&gt;&lt;p&gt;
Tedious but also necessary. A sofware system is a shared enterprise. It&#39;s not &quot;my&quot; code, it&#39;s &lt;i&gt;the project&#39;s code&lt;/i&gt;; I am just the person checking it into source control. As a discipline, programming is a craft not an art. PL/SQL is simply a device for turning data into business value. It&#39;s more important that other people on the team can work with our code than that it has our signature style. So let&#39;s not be precious about appearance. We must follow the rules, and save our self-expression for our poems and our tweets. 
&lt;br&gt;&lt;p&gt;
Above all, know this: there are no development standards without code reviews.       


</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/2967606424810879458/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/2967606424810879458' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2967606424810879458'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2967606424810879458'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2020/08/how-plsql-development-standards-work.html' title='How PL/SQL Development Standards work'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-9124128972365494186</id><published>2020-07-30T06:21:00.001-07:00</published><updated>2020-07-30T06:21:38.672-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Data Model"/><category scheme="http://www.blogger.com/atom/ns#" term="Database"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="SQL"/><title type='text'>Minimal declaration of foreign key columns</title><content type='html'>
Here is the full declaration of an inline foreign key constraint (referencing a primary key column on a table called PARENT):
&lt;pre&gt;
, parent_id number(12,0) constraint chd_par_fk foreign key references parent(parent_id)
&lt;/pre&gt;
But what is the fewest number of words required to implement the same constraint? Two. This does exactly the same thing:
&lt;pre&gt;
, parent_id references parent
&lt;/pre&gt;
The neat thing about this minimalist declaration is the child column inherits the datatype of the referenced primary key column. Here&#39;s what it looks like (with an odd primary key declaration, just to prove the point):
&lt;pre&gt; 
SQL&gt; create table parent1
  2  (parent_id number(15,3) primary key)
  3  /

Table PARENT1 created.

SQL&gt; create table child1
  2  ( id        number(12,0) primary key
  3   ,parent_id references parent1) 
  4  /

Table CHILD1 created.

SQL&gt; desc child1
Name      Null?    Type         
--------- -------- ------------ 
ID        NOT NULL NUMBER(12)   
PARENT_ID          NUMBER(15,3) 
SQL&gt; 
&lt;/pre&gt;
If we want to specify a name for the foreign key we need to include the &lt;code&gt;constraint&lt;/code&gt; keyword: 
&lt;pre&gt; 
SQL&gt; create table parent2
  2  (parent_id number(15,3) constraint par1_pk primary key)
  3  /

Table PARENT2 created.

SQL&gt; create table child2
  2  ( id        number(12,0) constraint chd2_pk primary key
  3   ,parent_id              constraint chd2_par2_fk references parent2) 
  4  /

Table CHILD2 created.

SQL&gt; desc child2
Name      Null?    Type         
--------- -------- ------------ 
ID        NOT NULL NUMBER(12)   
PARENT_ID          NUMBER(15,3) 
SQL&gt; 
&lt;/pre&gt;
This minimal declaration always references the parent table&#39;s primary key. Suppose we want to reference a unique key rather than the primary key. (I would regard this as a data model smell, but sometimes we need to do it.) To make this work we need merely explicitly reference the unique key column:  
&lt;pre&gt;
SQL&gt; create table parent3
  2  ( parent_id  number(15,3)          constraint par3_pk primary key
  3   ,parent_ref varchar2(16) not null constraint par3_uk unique
  4  )
  5  /

Table PARENT3 created.

SQL&gt; create table child3
  2  ( id         number(12,0) constraint chd3_pk primary key
  3   ,parent_ref              constraint chd3_par3_fk references parent3(ref)) 
  4  /

Table CHILD3 created.

SQL&gt; desc child3
Name       Null?    Type         
---------- -------- ------------ 
ID         NOT NULL NUMBER(12)   
PARENT_REF          VARCHAR2(16) 
SQL&gt; 
&lt;/pre&gt;
Hmmm, neat. What if we have a compound primary key? Well, that&#39;s another data model smell but it still works. Because we&#39;re constraining multiple columns we need to use a table level constraint and so the syntax becomes more verbose; we need to include the magic words &lt;code&gt;foreign key&lt;/code&gt;:
&lt;pre&gt;
SQL&gt; create table parent4
  2  ( parent_id  number(15,3)   
  3   ,parent_ref varchar2(16) 
  4   ,constraint par4_pk primary key (id, ref)
  5  )
  6  /

Table PARENT4 created.

SQL&gt; create table child4
  2  ( id number(12,0) constraint chd4_pk primary key
  3   ,parent_id
  4   ,parent_ref
  5   ,constraint chd4_par4_fk foreign key (parent_id, parent_ref) references parent4) 
  6  /

Table CHILD4 created.

SQL&gt; desc child4
Name       Null?    Type         
---------- -------- ------------ 
ID         NOT NULL NUMBER(12)   
PARENT_ID           NUMBER(15,3) 
PARENT_REF          VARCHAR2(16) 
SQL&gt; 
&lt;/pre&gt;
Okay, but supposing we change the declaration of the parent column, does Oracle ripple the change to the child table? 

&lt;pre&gt; 
SQL&gt; alter table parent4 modify parent_ref varchar2(24);

Table PARENT4 altered.

SQL&gt; desc child4
Name       Null?    Type         
---------- -------- ------------ 
ID         NOT NULL NUMBER(12)   
PARENT_ID           NUMBER(15,3) 
PARENT_REF          VARCHAR2(16) 
SQL&gt; 
&lt;/pre&gt;
Nope. And rightly so. This minimal syntax is a convenience when we&#39;re creating a table, but there&#39;s no object-style inheritance mechanism. 
&lt;br&gt;&lt;p&gt;
Generally I prefer a verbose declaration over minimalism, because clarity trumps concision. I appreciate the rigour of enforcing the same datatype on both ends of a foreign key constraint. However, I hope that in most cases our &lt;code&gt;CREATE TABLE&lt;/code&gt; statements have been generated from a data modelling tool. So I think this syntactical brevity is a neat thing to know about, but of limited practical use.  </content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/9124128972365494186/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/9124128972365494186' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/9124128972365494186'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/9124128972365494186'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2020/07/minimal-declaration-of-foreign-key.html' title='Minimal declaration of foreign key columns'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-3946568624523035260</id><published>2018-09-03T00:53:00.000-07:00</published><updated>2018-09-03T00:56:25.740-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="SIG"/><category scheme="http://www.blogger.com/atom/ns#" term="UKOUG"/><title type='text'>UKOUG London Development and Middleware event - free!</title><content type='html'>The Oracle development landscape is an extremely broad and complicated one these days. It covers such a wide range of tools, technologies and practices it is hard to keep up.
&lt;p&gt;
The UKOUG is presenting a day of sessions which can bring you up to speed. It&#39;s a joint initiative between the Development and Middleware SIGs - a composite if you will - at the Oracle City Office on Thursday 6th September. This event is free. If you are a UKOUG member attending it won&#39;t count against your allotment of SIG delegates; if you&#39;re not a UKOUG member there&#39;s no charge so come along and get a taste of what the UKOUG has to offer.
&lt;p&gt;
The day covers a broad spectrum. Martin Beeby is a popular speaker; his talk covers how Oracle is embracing new cool technologies such as Blockchain, Docker and chatbots. There are talks from Oracle ACE Director Simon Haslam on mobile applications and Oracle ACE Director Mark Simpson on real-life uses for AI. There are also sessions on API design, building bots and JavaScript frameworks.
&lt;p&gt;
Even last year these things might have been considered cutting edge, certainly in the enterprise realm. But most organisations of whatever size are at least thinking about or running Proof of Concept projects in AI or blockchain. Some already have these technologies active in Production. These things will affect everybody working in IT, and probably sooner rather than later. It&#39;s always good to know what&#39;s coming.
&lt;p&gt;
&lt;a href=&quot;http://www.ukoug.org/events/ukoug-development-middleware-and-integration-sig/&quot;&gt;Check out the full agenda here&lt;/a&gt;.&lt;br/&gt;
&lt;a href=&quot;https://www.ukoug.org/membersarea/login/login.asp?type=OTHER&amp;Dest=%2E%2E%2FMultiEvents%2FcreateBooking%2Easp%3Fcode%3DEG1283%26Book%3D&quot;&gt;Register here.&lt;/a&gt; 
&lt;p&gt;
Oh, and did I mention it&#39;s free? Treat yourself to a day out from the present and get a glimpse of the future. </content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/3946568624523035260/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/3946568624523035260' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/3946568624523035260'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/3946568624523035260'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2018/09/ukoug-london-development-and-middleware.html' title='UKOUG London Development and Middleware event - free!'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-5385003436293451258</id><published>2018-05-31T14:14:00.001-07:00</published><updated>2018-05-31T14:14:05.652-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="solid"/><title type='text'>The Single Responsibility principle</title><content type='html'>The Single Responsibility principle is the foundation of modular programming, and is probably the most important principle in the SOLID set. Many of the other principles flow from it.
&lt;br/&gt;&lt;br/&gt;
It is quite simple: a program unit should do only one thing. A procedure should implement a single task; a package should gather together procedures which solve a set of related tasks. Consider &lt;a href=&quot;https://docs.oracle.com/cloud/latest/db121/ARPLS/u_file.htm#ARPLS70896&quot;&gt;the Oracle library package &lt;code&gt;UTL_FILE&lt;/code&gt;&lt;/a&gt;. Its responsibility is quite clear: it is for working with external files. It implements all the operations necessary to work with OS files: opening them, closing them, reading and writing, etc. It defines a bespoke suite of exceptions too. 
&lt;br/&gt;&lt;br/&gt;
Each procedure in the package has a clear responsibility too. For instance, &lt;code&gt;fclose()&lt;/code&gt; closes a single referenced file whereas &lt;code&gt;fclose_all()&lt;/code&gt; closes all open files. Now, the package designers could have implemented that functionality as a single procedure, with different behaviours depending on whether the &lt;code&gt;file&lt;/code&gt; parameter was populated or unpopulated. This might seem a simpler implementation, because it would be one fewer procedure. But the interface has actually become more complicated: essentially we have a flag parameter, which means we need to know a little bit more about the internal processing of &lt;code&gt;fclose()&lt;/code&gt;. It would have made the package just a little bit harder to work with without saving any actual code.
&lt;br/&gt;&lt;br/&gt;
Of course, it&#39;s pretty easy to define the Single Responsibility of a low level feature like file handling. We might think there are some superficially similarities with displaying information to the screen but it&#39;s fairly obvious that these are unrelated and so we need tow packages, &lt;code&gt;UTL_FILE&lt;/code&gt; and &lt;code&gt;DBMS_OUTPUT&lt;/code&gt;. When it comes to our own code, especially higher level packages, it can be harder to define the boundaries. At the broadest level we can define domains - SALES, HR, etc. But we need more than one package per domain: how do we decide the responsibilities of indvidual pacakages?
&lt;br/&gt;&lt;br/&gt;
Robert C Martin defines &lt;a href=&quot;https://www.hanselminutes.com/145/solid-principles-with-uncle-bob-robert-c-martin&quot;&gt;the  Single Responsibility principle&lt;/a&gt; as: &quot;A class should have only one reason to change.&quot; Reasons for change can be many and various. In database applications dependence on tables is a primary one. So procedures which work a common set of table may well belong together. But there are at least two sets of privileges for data: reading and manipulating. So it&#39;s likely we will need a package which gathers together reporting type queries which can be granted to read-only users and a package which executes DML statements which can be granted to more privileged users. Maybe our domain requires special processing, such as handling sensitive data; procedures for implementing that business logic will belong in separate packages. 
&lt;br/&gt;&lt;br/&gt;
Single responsibility becomes a matrix, with dependencies along one access and audience of users along another. 
&lt;br/&gt;&lt;br/&gt;
The advantages of Singel Responsibility should be obvious. It allows us to define a cohesive package, collecting together all the related functionality which makes it easy for others reuse it. It also allows us to define private routines in a package body, which reduces the amount of code we have to maintain while giving us a mechanism for preventing other developers from using it. Restricting the features to a single responsibility means unrelated functions are not coupled together. This gives a better granularity for granting the least privileges necessary to users of our code.  


&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/5385003436293451258/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/5385003436293451258' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/5385003436293451258'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/5385003436293451258'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2018/05/the-single-responsibility-principle.html' title='The Single Responsibility principle'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-2936424440047417654</id><published>2018-04-15T00:55:00.000-07:00</published><updated>2018-04-23T23:36:14.358-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DESIG"/><category scheme="http://www.blogger.com/atom/ns#" term="Development"/><category scheme="http://www.blogger.com/atom/ns#" term="NorTech18"/><category scheme="http://www.blogger.com/atom/ns#" term="UKOUG"/><title type='text'>UKOUG Northern Technology Summit 2018</title><content type='html'>The UKOUG has run something called the Northern Server Day for several years. &lt;i&gt;Northern&lt;/i&gt; because they were held in a northern part of England (but south of Scotland) and &lt;i&gt;Server&lt;/i&gt; because the focus was the database server. Over the last couple of years the day has had several streams, covering Database, High Availability and Engineered Systems. So primarily a day for DBAs and their ilk.
&lt;br/&gt;&lt;br/&gt;
This year the event has expanded to let in the developers. Yay! 
&lt;br/&gt;&lt;br/&gt;
The &lt;a href=&quot;http://www.ukoug.org/2018-events/ukoug-northern-technology-summit-2018/&quot;&gt;Northern Technology Summit 2018&lt;/a&gt; is effectively a mini-conference: in total there are five streams - Database, RAC Cloud Infrastructure &amp; Availability, Systems, APEX and Development. But for registration it counts as a SIG. So it&#39;s free for UKOUG members to attend. What astonishingly good value!&lt;sup&gt;&lt;a href=&quot;#fn1&quot; id=&quot;ref1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; And it doesn&#39;t affect your entitlement to attend the annual conference in December. 
&lt;H2&gt;The Development stream&lt;/h2&gt;
The Development stream covers a broad range of topics. Application development in 2018 is a tangled hedge with new technologies like Cloud, AI and NoSQL expanding the ecosystem but not displacing the traditional database and practices. The Development stream presents a mix of sessions from the new-fangled and Old Skool ends of the spectrum.
&lt;br&gt;&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;The New Frontier: Mobile and AI Powered Conversational Apps.&lt;/b&gt; Oracle are doing interesting work with AI and Grant Ronald is king of the chatbots. This is an opportunity to find out what modern day apps can do. 
&lt;li&gt;&lt;b&gt;The New Frontier: Mobile and AI Powered Conversational Apps.&lt;/b&gt; Oracle are doing interesting work with AI and Grant Ronald is king of the chatbots. This is an opportunity to find out what modern day apps can do. 
&lt;li&gt;&lt;b&gt;Building a Real-Time Streaming Platform with Oracle, Apache Kafka, and KSQL&lt;/b&gt; No single technology is a good fit for all enterprise problems. Robin Moffat of Confluent will explain how we can use Apache Kafka to handle event-based data processing. 
&lt;li&gt;&lt;b&gt;Modernising Oracle Forms Applications with Oracle Jet&lt;/b&gt; Oracle Forms was&lt; - still is - a highly-productive tool for building OLTP front-ends. There are countless organisations still running Forms applications. But perhaps the UX looks a little jaded in 2018. So here&#39;s Mark Waite from Griffiths Waite to show how we can use Oracle&#39;s JET JavaScript library to write new UIs without having to re-code the whole Forms application.
&lt;li&gt;&lt;b&gt;18(ish) Things Developers Will Love about Oracle Database 18c&lt;/b&gt; Oracle&#39;s jump to year-based release numbers doesn&#39;t make live easier for presenters: ten things about 10c was hard enough. But game for a challenge, Oracle&#39;s Chris Saxon attempts to squeeze as many new features as possible into his talk.
&lt;li&gt;&lt;b&gt;Modernize Your Development Experience With Oracle Cloud&lt;/b&gt; Cloud isn&#39;t just something for the sysadmins, there&#39;s a cloud for developers too. Sai Janakiram Penumuru from DXC Technology will explain how Oracle Developer Cloud might revolutionise your development practices.
&lt;li&gt;&lt;b&gt;Designing for Deployment&lt;/b&gt; As &lt;a href=&quot;https://www.joelonsoftware.com/2009/09/23/the-duct-tape-programmer/&quot; alt=&quot;Joel on Software, &#39;The duct tape programmer&#39;&quot;&gt;Joel Spolsky says, shipping is a feature&lt;/a&gt;. But it&#39;s a feature which is hard to retrofit. In this talk I will discuss some design principles which make it easier to build, deploy and ship database applications.
&lt;/ul&gt;
&lt;H2&gt;Everything else&lt;/h2&gt;
So I hope the Development stream offers a day of varied and useful ideas. There are things you might be able to use right now or in the next couple of months, and things which might shape what you&#39;ll be doing next year. But it doesn&#39;t matter if not everything floats your boat. The cool thing about the day is that delegates can attend any of the streams. &lt;sup&gt;&lt;a href=&quot;#fn2&quot; id=&quot;ref2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; .
&lt;br/&gt;&lt;br/&gt;So you can listen to Nigel Bayliss talking about Optimisation in the Database Stream, Vipul Sharma: talking about DevOps in the Availability stream, Anthony talking about Kubernetes in the Systems stream and John Scott talking about using Docker with Oracle in the Apex stream. There are sessions on infrastructure as code, upgrading Oracle 12cR1 to 12cR2, GDPR (the new EU data protection law), the Apex Interactive grid, Apache Impala, and Cloud, lots of Cloud. Oh my!&lt;br&gt;&lt;br&gt;
&lt;a href=&quot;http://www.oug.org/nts/2018/agenda.pdf alt=&quot;UKOUG Northern Technology Summit 2018 agenda&quot;&gt;The full agenda is here (pdf).&lt;/a&gt;
&lt;h2&gt;Register now&lt;/h2&gt;
So if you&#39;re working with Oracle technology and you want to attend this is what you need to know:
&lt;ul&gt;
&lt;li&gt;Date: 16th May 2018
&lt;li&gt;Location: &lt;a href=&quot;https://www.parkplaza.com/leeds-hotel-gb-ls1-5ns/gbleeds&quot;&gt;Park Plaza Hotel, Leeds&lt;/a&gt;
&lt;li&gt;Cost: Free for UKOUG members. There is a fee for non-members but frankly you might as well buy &lt;a href=&quot;http://www.ukoug.org/membership-new/membership-fees/bronze-membership/&quot;&gt;bronze membership package&lt;/a&gt; and get a whole year&#39;s work of access to UKOUG events (including the annual conference). It&#39;s a bargain. 
&lt;/ul&gt;
&lt;hr&gt;

&lt;sup id=&quot;fn1&quot;&gt;1. The exact number of SIG passes depends on the membership package you have&lt;a href=&quot;#ref1&quot; title=&quot;Jump back to footnote 1 in the text.&quot;&gt;↩&lt;/a&gt;&lt;/sup&gt;
&lt;br&gt; 
&lt;sup id=&quot;fn2&quot;&gt;2. The registration process requires you to pick a stream but that is just for administrative purposes. It&#39;s not a lock-in.&lt;a href=&quot;#ref2&quot; title=&quot;Jump back to footnote 2 in the text.&quot;&gt;↩&lt;/a&gt;&lt;/sup&gt; </content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/2936424440047417654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/2936424440047417654' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2936424440047417654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2936424440047417654'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2018/04/ukoug-northern-technology-summit-2018.html' title='UKOUG Northern Technology Summit 2018'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-7542989752166578553</id><published>2017-12-31T09:56:00.000-08:00</published><updated>2017-12-31T09:59:37.098-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="interfaces"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><title type='text'>Data Access Layer vs Table APIs </title><content type='html'>One of the underlying benefits of PL/SQL APIs is the enabling of data governance. Table owners can shield their tables behind a layer of PL/SQL. Other users have no access to the tables directly but only through stored procedures. This confers many benefits:
&lt;ul&gt;
&lt;li&gt;Calling programs code against a programmatic interface. This frees the table owner to change the table&#39;s structure whenever it&#39;s necessary without affecting its consumers.
&lt;li&gt;Likewise the calling programs get access to the data they need without having to know the details of the table structure, such as technical keys. 
&lt;li&gt;The table owner can use code to enforce complicated business rules when data is changed.
&lt;li&gt;The table owner can enforce sophisticated data access policies (especially for applications using Standard Edition without DBMS_RLS).
&lt;/ul&gt;
So naturally the question arises, is this the same as Table APIs?
&lt;br/&gt;&lt;br/&gt;
Table APIs used to be a popular approach to encapsulating tables. The typical Table API comprised two packages per table; one package provided methods for inserting, updating and deleting records, and the other package provided query methods. The big attraction of Table APIs was that they could be 100% generated from the data dictionary - both Oracle Designer and Steven Feuerstein&#39;s QNXO library provided TAPI generators. And they felt like good practice because, y&#39;know, access to the tables was shielded by a PL/SQL layer.
&lt;br/&gt;&lt;br/&gt;
But there are several problems with Table APIs.
&lt;br/&gt;&lt;br/&gt; The first is that they entrench row-by-agonising-row processing. Table APIs have their roots in early versions of Oracle so the DML methods only worked with a single record. Even after Oracle 8 introduced PL/SQL collection types TAPI code in the wild tended to be RBAR: there seems to something in the brain of the average programmer which predisposes them to prefer loops executing procedural code rather than set operations.
&lt;br/&gt;&lt;br/&gt; The second is that they prevent SQL joins. Individual records have to be selected from one table to provide keys for looking up records in a second table. Quite often this leads to loops within loops. So-called PL/SQL joins prevent the optimizer from choosing good access paths when handling larger amounts of data.
&lt;br/&gt;&lt;br/&gt;The third issue is that it is pretty hard to generate methods for all conceivable access paths. Consequently the generated packages had a few standard access paths (primary key, indexed columns) and provided an dynamic SQL method which accepted a free text WHERE clause. Besides opening the package to SQL injection this also broke &lt;a href=&quot;https://en.wikipedia.org/wiki/Law_of_Demeter&quot;&gt;the Law of Demeter&lt;/a&gt;: in order to pass a dynamic WHERE clause the calling program needed to know the structure of the underlying table, which defeats the whole objective of encapsulation.
&lt;br/&gt;&lt;br/&gt;Which leads on to the fourth, more philosophical problem with Table APIs: there is minimal abstraction. Each package is generated so it fits very closely to the structure of the Table. If the table structure changes we have to regenerate the TAPI packages: the fact that this can be done automatically is scant recompense for the tight coupling between the Table and the API.
&lt;br/&gt;&lt;br/&gt; So although Table APIs could be mistaken for good practice in actuality they provide no real benefit. The interface is 1:1 with the table structure so it has no advantage over granting privileges on the table. Combined with the impact of RBAR processing and PL/SQL joins on performance and the net effect of Table APIs is disastrous.
&lt;br/&gt;&lt;br/&gt;
We cannot generate good Data Access APIs: we need to write them. This is because the APIs should be built around business functions rather than tables. The API packages granted to other users should comprise procedures for executing transactions. A Unit Of Work is likely to touch more than one table. These have to be written by domain experts who understand the data model and the business rules. &lt;br/&gt;  &lt;br/&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;

   </content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/7542989752166578553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/7542989752166578553' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/7542989752166578553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/7542989752166578553'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2017/12/data-access-layer-vs-table-apis.html' title='Data Access Layer vs Table APIs '/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-330968197871552924</id><published>2017-12-29T10:14:00.000-08:00</published><updated>2017-12-30T08:07:27.720-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Community"/><category scheme="http://www.blogger.com/atom/ns#" term="StackOverflow"/><title type='text'>On hitting 100K on StackOverflow</title><content type='html'>100,000 is just another number. It&#39;s one more than 99,999. And yet, and yet. We live in a decimal cultural. We love to see those zeroes roll up. Order of magnitude baby! It&#39;s the excitement of being a child, going on a journey in the family car when the odometer reads &lt;code&gt;99994&lt;/code&gt;. knowing you&#39;ll see &lt;code&gt;100000&lt;/code&gt;. Of course everybody got distracted by the journey and next time you look at the dial it reads &lt;code&gt;100002&lt;/code&gt;.
&lt;br/&gt;&lt;br/&gt;
Earlier this year my StackOverflow reputation passed 100,000. Like the car journey I missed the actual moment. My rep had been 99,986  when I last checked the previous evening and 100,011 the next day. Hey ho. 
&lt;br/&gt;&lt;br/&gt;
Reputation is a big deal on StackOverflow because it is the prime measure of contribution. As a Q&amp;A site (&lt;b&gt;not&lt;/b&gt; a forum - that confuses a lot of people) it needs content, it needs good questions and good answers. Reputation points are the reward for good posts. In this context &lt;i&gt;good&lt;/i&gt; is determined democratically: people vote up good questions and good answers, and - crucially - vote down poor questions and answers. Votes are the main way of gaining reputation points: &lt;b&gt;+5&lt;/b&gt; for an upvoted question, &lt;b&gt;+10&lt;/b&gt; for an upvoted answer and &lt;b&gt;+15&lt;/b&gt; for an accepted answer. (There are &lt;a href=&quot;https://stackoverflow.com/help/whats-reputation&quot; alt=&quot;StackOverflow FAQ&quot;&gt;other ways of gaining - and losing - rep)&lt;/a&gt; but posting is the main one. 
&lt;blockquote&gt;

&quot;Reputation is a rough measurement of how much the community trusts you; it is earned by convincing your peers that you know what you’re talking about.&quot; &lt;a href=&quot;https://meta.stackexchange.com/questions/7237/how-does-reputation-work/7238#7238&quot;&gt;Meta Stack Exchange FAQ&lt;/a&gt;
&lt;/blockquote&gt;

&lt;br/&gt;&lt;br/&gt;
So is reputation just a way of keeping score? Nope: it is gamification but there is more to it than that. 
Reputation means points and what do points make? &lt;s&gt;Prizes&lt;/s&gt; Privileges. StackOverflow is largely a self-policing community. There are full-on (elected) moderators but most moderation is actually carried out by regular SO users with sufficient rep. Somebody has asked an unclear question: once you have 50 rep you can post a comment asking for clarification. Got a user who doesn&#39;t know how to turn off the &lt;code&gt;CAPSLOCK&lt;/code&gt; key? With 2000 rep you can just edit their post and apply sentence case. And so on.
&lt;br/&gt;&lt;br/&gt;
Hmmm, so StackOverflow rewards its keenest contributors by allowing them to do chores around the site. Yes and it works. One of the big problems with forums is other users. Not griefers as such but there are a lot of low-level irritations: users who don&#39;t know how to search the site, or how to format their posts, or just generally fail to understand etiquette. Granting increasing moderation privileges at reputation milestones allows committed users to smooth away soem of those irritations. 
&lt;br/&gt;&lt;br/&gt;
But still, getting to 100,000 took eight years and almost 3000 answers. Was it worth it? Of course. It&#39;s nice to give back to the community. We are here to help: upvotes and accepted answers provide a nice feedback that we&#39;ve succeeded. Downvotes also provide a necessary corrective (even if it is annoying when some rando dings you on an answer from five years back without leaving comment). And while there are no prizes, when you get to 100,000 you do get swag. A big box of swag:
&lt;br/&gt;&lt;br/&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbrCLdVoCaTPvEjmO6sgZZv3X8MQeHx375X58wE3XP2SgT6nT2kkDdNnfqKAXL9QOZzbH_WFpWzlasFRUU67l6GtaZ1nag-UXQWPBh-y8hk0YI2qdYN3J61YMNhyZROE8dGT6uBg/s1600/IMG_20171001_130349327.jpg&quot;  imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbrCLdVoCaTPvEjmO6sgZZv3X8MQeHx375X58wE3XP2SgT6nT2kkDdNnfqKAXL9QOZzbH_WFpWzlasFRUU67l6GtaZ1nag-UXQWPBh-y8hk0YI2qdYN3J61YMNhyZROE8dGT6uBg/s320/IMG_20171001_130349327.jpg&quot; width=&quot;320&quot; height=&quot;180&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;900&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br/&gt;&lt;br/&gt;

Here is the box with a standard reference pear so you can see just how big it is.


&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDFGUyGYJy-AreH1D9onzkCEuNW3cwSQicSTUN-LIaw2UuY_3HFFy7gPr6OLjA93OuUMZnQbLvu0yQ-UB1V2lzyBiT0_4CYLr0j0hD1qjXA4Zgzxd40Wr1Vt1M6PPXHQ48uy9G8g/s1600/IMG_20171001_130419942.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDFGUyGYJy-AreH1D9onzkCEuNW3cwSQicSTUN-LIaw2UuY_3HFFy7gPr6OLjA93OuUMZnQbLvu0yQ-UB1V2lzyBiT0_4CYLr0j0hD1qjXA4Zgzxd40Wr1Vt1M6PPXHQ48uy9G8g/s320/IMG_20171001_130419942.jpg&quot; width=&quot;320&quot; height=&quot;180&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;900&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br/&gt;&lt;br/&gt;

Inside there is - a pen ....

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_BRgm2AJ7fnmLkZMkRmHgkfGqx9RLBuGWldI50_3FW7oiJFH9EJw5Kz1OLPuT_uam6t-CTpXiE6ti9_ZU-U3Nfn-IRVftb4FBuz-D_M0bGIODdi08OYOlpUAkYedMMaHHw1_fxA/s1600/IMG_20171001_131328200.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_BRgm2AJ7fnmLkZMkRmHgkfGqx9RLBuGWldI50_3FW7oiJFH9EJw5Kz1OLPuT_uam6t-CTpXiE6ti9_ZU-U3Nfn-IRVftb4FBuz-D_M0bGIODdi08OYOlpUAkYedMMaHHw1_fxA/s320/IMG_20171001_131328200.jpg&quot; width=&quot;320&quot; height=&quot;180&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;900&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br/&gt;&lt;br/&gt;

Some stickers ....

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh51dKNRHSVI5Lq2MwOMlIRMtxtFviPo3W8JPYHsCsILlHhCu0z9gG9LR9_2n39G0_J1kHGOzzy8CWrJxL8Nn_4VkROQXPjag0o1ZlEoZ7S50lJSpq6FiOSrgKSAE_4hHaRCcFwnQ/s1600/IMG_20171001_131017020_HDR.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh51dKNRHSVI5Lq2MwOMlIRMtxtFviPo3W8JPYHsCsILlHhCu0z9gG9LR9_2n39G0_J1kHGOzzy8CWrJxL8Nn_4VkROQXPjag0o1ZlEoZ7S50lJSpq6FiOSrgKSAE_4hHaRCcFwnQ/s320/IMG_20171001_131017020_HDR.jpg&quot; width=&quot;320&quot; height=&quot;180&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;900&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br/&gt;&lt;br/&gt;

A StackOverflow T-shirt (I have negotiated with my better half to keep this one) ...

&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkwBoKcrGODQc9KrjKtZz_AM8poKA_ey0nyRxtEMy0lC52kpm5SDXmI0-c2dmkul2zAeJ2MicLVN5w8Fr7b1h3iV0Bq8LsP-YBnEXesD5j-TAopbAj2AG5dNKeaPdUnl-gqnRg0A/s1600/IMG_20171001_131432360.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgkwBoKcrGODQc9KrjKtZz_AM8poKA_ey0nyRxtEMy0lC52kpm5SDXmI0-c2dmkul2zAeJ2MicLVN5w8Fr7b1h3iV0Bq8LsP-YBnEXesD5j-TAopbAj2AG5dNKeaPdUnl-gqnRg0A/s320/IMG_20171001_131432360.jpg&quot; width=&quot;320&quot; height=&quot;180&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;900&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br/&gt;&lt;br/&gt;

And an over-sized coffee mug...
 
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinZDeG8pxhjTMsyAbp8sWdrXN3w2rl9nQTtBIyx2TK4LA3TQcQmBoisbYT5sVshTXbvdYIaKz4HhdvPct7PWduignSpQ6RkML2sn7NDl8i-gQ2x6pRcqJa2hNntfLDSA2BHAc_rg/s1600/IMG_20171001_131250326.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEinZDeG8pxhjTMsyAbp8sWdrXN3w2rl9nQTtBIyx2TK4LA3TQcQmBoisbYT5sVshTXbvdYIaKz4HhdvPct7PWduignSpQ6RkML2sn7NDl8i-gQ2x6pRcqJa2hNntfLDSA2BHAc_rg/s320/IMG_20171001_131250326.jpg&quot; width=&quot;320&quot; height=&quot;180&quot; data-original-width=&quot;1600&quot; data-original-height=&quot;900&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;br/&gt;&lt;br/&gt;

One more thing. There are also badges. Badges are nudges to encourage desirable behaviour such as editing posts, voting in moderator elections, reviewing posts, offering bounties, being awesome. Because let&#39;s face it, badges are cool. More badges = more flair. &lt;a href=&quot;https://www.youtube.com/watch?v=KJtrLKGZZFg&quot; alt=&quot;YouTube &#39;Office Space&#39;&quot;&gt;And who doesn&#39;t want more flair?&lt;/a&gt;
Got flair? Heck yeah!
&lt;br/&gt;&lt;br/&gt;

&lt;a href=&quot;https://stackoverflow.com/users/146325/apc&quot;&gt;
&lt;img src=&quot;https://stackoverflow.com/users/flair/146325.png&quot; width=&quot;208&quot; height=&quot;58&quot; alt=&quot;profile for APC at Stack Overflow, Q&amp;amp;A for professional and enthusiast programmers&quot; title=&quot;profile for APC at Stack Overflow, Q&amp;amp;A for professional and enthusiast programmers&quot;&gt;
&lt;/a&gt;



</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/330968197871552924/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/330968197871552924' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/330968197871552924'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/330968197871552924'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2017/12/on-hitting-100k-on-stackoverflow.html' title='On hitting 100K on StackOverflow'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbrCLdVoCaTPvEjmO6sgZZv3X8MQeHx375X58wE3XP2SgT6nT2kkDdNnfqKAXL9QOZzbH_WFpWzlasFRUU67l6GtaZ1nag-UXQWPBh-y8hk0YI2qdYN3J61YMNhyZROE8dGT6uBg/s72-c/IMG_20171001_130349327.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-4046554028654397005</id><published>2017-05-31T15:10:00.000-07:00</published><updated>2017-05-31T15:10:29.476-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="software architecture"/><title type='text'>Avoiding Coincidental Cohesion</title><content type='html'>Given that Coincidental Cohesion is bad for our code base so obviously we want to avoid writing utilities packages. Fortunately it is mostly quite easy to do so. It requires vigilance on our part.
Utilities packages are rarely planned. More often we are writing a piece of business functionality when we find ourselves in need of some low level functionality. It doesn&#39;t fit in the application package we&#39;re working on, perhaps we suspect that it might be more generally useful, so we need somewhere to put it.   
&lt;p&gt;&lt;br/&gt;
The important thing is to recognise and resist the temptation of the Utilities package. The name itself (and similarly vague synonyms like helper or utils) should be a red flag. When we find ourselves about to type &lt;code&gt;create or replace package utilities&lt;/code&gt; we need to stop and think: what would be a better name for this package? Consider whether there are related functions we might end up needing? Suppose we&#39;re about to write a function to convert a date into Unix epoch string. It doesn&#39;t take much imagine to think we might need a similar function to convert a Unix timestamp into a date. We don&#39;t need to write that function now but let&#39;s start a package dedicated to Time functions instead of a miscellaneous utils package.
&lt;p&gt;&lt;br/&gt;
Looking closely at &lt;a href=&quot;DBMS_Utility 12cR2 https://docs.oracle.com/database/122/ARPLS/DBMS_UTILITY.htm&quot;&gt;the programs which comprise the &lt;code&gt;DBMS_UTILITY&lt;/code&gt; package&lt;/a&gt; it is obviously unfair to describe them as a random selection. In fact that there seven or eight groups of related procedures. 
&lt;p&gt;&lt;br/&gt;
&lt;b&gt;DB Info&lt;/b&gt;&lt;br/&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;INSTANCE_RECORD&lt;/code&gt; Record Type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DBLINK_ARRAY&lt;/code&gt; Table Type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;INSTANCE_TABLE&lt;/code&gt; Table Type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ACTIVE_INSTANCES&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;CURRENT_INSTANCE&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;DATA_BLOCK_ADDRESS_BLOCK&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;DATA_BLOCK_ADDRESS_FILE&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;DB_VERSION&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;GET_ENDIANNESS&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;GET_PARAMETER_VALUE&lt;/code&gt; Function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IS_CLUSTER_DATABASE&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;MAKE_DATA_BLOCK_ADDRESS&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;PORT_STRING&lt;/code&gt; Function&lt;/li&gt; 
&lt;/ul&gt;
&lt;b&gt;Runtime Messages&lt;/b&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FORMAT_CALL_STACK&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;FORMAT_ERROR_BACKTRACE&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;FORMAT_ERROR_STACK&lt;/code&gt; Function&lt;/li&gt; 
&lt;/ul&gt;
&lt;b&gt;Object Management&lt;/b&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;COMMA_TO_TABLE&lt;/code&gt; Procedures&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;COMPILE_SCHEMA&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;CREATE_ALTER_TYPE_ERROR_TABLE&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;INVALIDATE&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;TABLE_TO_COMMA&lt;/code&gt; Procedures&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;VALIDATE&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;/ul&gt;
&lt;b&gt;Object Info (Object Management?)&lt;/b&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;INDEX_TABLE_TYPE&lt;/code&gt; Table Type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LNAME_ARRAY&lt;/code&gt; Table Type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAME_ARRAY&lt;/code&gt; Table Type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NUMBER_ARRAY&lt;/code&gt; Table Type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UNCL_ARRAY&lt;/code&gt; Table Type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CANONICALIZE&lt;/code&gt; Procedure&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET_DEPENDENCY&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;NAME_RESOLVE&lt;/code&gt; Procedure&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NAME_TOKENIZE&lt;/code&gt; Procedure&lt;/li&gt;
&lt;/ul&gt;
&lt;b&gt;Session Info&lt;/b&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;OLD_CURRENT_SCHEMA&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;OLD_CURRENT_USER&lt;/code&gt; Function&lt;/li&gt; 
&lt;/ul&gt;
&lt;b&gt;SQL Manipulation&lt;/b&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;EXPAND_SQL_TEXT&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;GET_SQL_HASH&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;SQLID_TO_SQLHASH&lt;/code&gt; Function&lt;/li&gt; 
&lt;/ul&gt;
&lt;b&gt;Statistics&lt;/b&gt; (deprecated))&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ANALYZE_DATABASE&lt;/code&gt; Procedure&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ANALYZE_PART_OBJECT&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;ANALYZE_SCHEMA&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;/ul&gt;
&lt;b&gt;Time&lt;/b&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET_CPU_TIME&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;GET_TIME&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;GET_TZ_TRANSITIONS&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;/ul&gt;
&lt;b&gt;Unclassified&lt;/b&gt;&lt;br/&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WAIT_ON_PENDING_DML&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;EXEC_DDL_STATEMENT&lt;/code&gt; Procedure&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;GET_HASH_VALUE&lt;/code&gt; Function&lt;/li&gt; 
&lt;li&gt;&lt;code&gt;IS_BIT_SET&lt;/code&gt; Function&lt;/li&gt; 
&lt;/ul&gt;&lt;p&gt;&lt;br/&gt;
We can see an alternative PL/SQL code suite, with several highly cohesive packages. But there will be some procedures which are genuinely unrelated to anything else. The four procedures in the &lt;b&gt;Unclassified&lt;/b&gt; section above are examples. But writing a miscellaneous utils package for these programs is still wrong. There are better options. 
&lt;ol&gt;
&lt;li&gt;Find a home. It&#39;s worth considering whether we already have a package which would fit the new function. Perhaps &lt;code&gt;WAIT_ON_PENDING_DML()&lt;/code&gt; should have gone in &lt;code&gt;DBMS_TRANSACTION&lt;/code&gt;; perhaps &lt;code&gt;IS_BIT_SET()&lt;/code&gt; properly belongs in &lt;code&gt;UTL_RAW&lt;/code&gt;.
&lt;li&gt;A package of their own. Why not? It may seem extravagant to have a package with a single procedure but &lt;a href=&quot;https://docs.oracle.com/database/121/ARPLS/d_dg.htm#ARPLS66222&quot;&gt;consider &lt;code&gt;DBMS_DG&lt;/code&gt;&lt;/a&gt; with its lone procedure &lt;code&gt;INITIATE_FS_FAILOVER()&lt;/code&gt;. The package delivers the usual architectural benefits plus it provides a natural home for related procedures we might discover a need for in the future.
&lt;li&gt;Standalone procedure. Again, why not? We are so conditioned to think of a PL/SQL program as a package that we forget it can be just a Procedure or Function. Some programs are suited to standalone implementation.   
&lt;/ol&gt; 
&lt;p&gt;&lt;br/&gt;
So avoiding the Utilities package requires vigilance. Code reviews can help here. Preventing the Utilities package becoming entrenched is crucial: once we have a number of packages dependent on a Utilities package it is pretty hard to get rid of it. And once it becomes a fixture in the code base developers will consider it more acceptable to add procedures to it.   
&lt;p&gt;&lt;br/&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;

  

 



</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/4046554028654397005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/4046554028654397005' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/4046554028654397005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/4046554028654397005'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2017/05/avoiding-coincidental-cohesion.html' title='Avoiding Coincidental Cohesion'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-8524462704033273745</id><published>2017-05-31T13:42:00.000-07:00</published><updated>2017-05-31T13:46:31.280-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="software architecture"/><title type='text'>Utilities - the Coincidental Cohesion anti-pattern </title><content type='html'>One way to understand the importance of cohesion is to examine an example of a non-cohesive package, one exhibiting a random level of cohesion. The poster child for Coincidental Cohesion is the utility or helper package. Most applications will have one or more of these, and Oracle&#39;s PL/SQL library is no exception. &lt;code&gt;DBMS_UTILITY&lt;/code&gt; has 37 distinct procedures and functions (i.e. not counting overloaded signatures) in 11gR2 and 38 in 12cR1 (and R2). Does &lt;code&gt;DBMS_UTILITY&lt;/code&gt; deliver any of the benefits the PL/SQL Reference says packages deliver? 
&lt;h3&gt;Easier Application Design?&lt;/h3&gt; 
One of the characteristics of utilities packages is that they aren&#39;t designed in advance. They are the place where functionality ends up because there is no apparently better place for it. Utilities occur when we are working on some other piece of application code; we  discover a gap in the available functionality such as hashing a string. When this happens we generally need the functionality &lt;i&gt;now&lt;/i&gt;: there&#39;s little benefit to deferring the implementation until later. So we write a &lt;code&gt;GET_HASH_VALUE()&lt;/code&gt; function,x stick it in our utilities package and proceed with the task at hand. 
&lt;P&gt;
The benefit of this approach is we keep our focus on the main job, delivering business functionality. The problem is, we never go back and re-evaluate the utilities. Indeed, now there is business functionality which depends on them: refactoring utilities introduces risk. Thus the size of the utilities package slowing increases, one tactical implementation at a time. 
&lt;h3&gt;Hidden Implementation Details?&lt;/h3&gt;  
Another characteristic of utility functions is that they tend not to share concrete implementations. Often a utilities package beyond a certain size will have groups of procedures with related functionality. It seems probable that &lt;code&gt;DBMS_UTILITY.ANALYZE_DATABASE()&lt;/code&gt;, &lt;code&gt;DBMS_UTILITY.ANALYZE_PART_OBJECT()&lt;/code&gt; and &lt;code&gt;DBMS_UTILITY.ANALYZE_SCHEMA()&lt;/code&gt; share some code. So there are benefits to co-locating them in the same package. But it is unlikely that &lt;code&gt;CANONICALIZE()&lt;/code&gt; , &lt;code&gt;CREATE_ALTER_TYPE_ERROR_TABLE()&lt;/code&gt; and &lt;code&gt;GET_CPU_TIME()&lt;/code&gt; have much code in common. 
&lt;h3&gt;Added Functionality?&lt;/h3&gt;  
Utility functions are rarely part of a specific business process. They are usually called on a one-off basis rather than being chained together. So there is no state to be maintained across different function calls. 
&lt;h3&gt;Better Performance?&lt;/h3&gt;  
For the same reason there is no performance benefit from a utilities package. Quite the opposite. When there is no relationship between the functions we cannot make predictions about usage. We are not likely to call &lt;code&gt;EXPAND_SQL_TEXT()&lt;/code&gt; right after calling &lt;code&gt;PORT_STRING()&lt;/code&gt;. So there is no benefit in loading the former into memory when we call the latter. In fact the performance of &lt;code&gt;EXPAND_SQL_TEXT()&lt;/code&gt;  is impaired because we have to load the whole &lt;code&gt;DBMS_UTILITY&lt;/code&gt; package into the shared pool, plus it uses up a larger chunk of memory until it gets aged out. Although to be fair, in these days of abundant RAM, some unused code in the library cache need not be our greatest concern. But whichever way we bounce it, it&#39;s not a boon.  
&lt;h3&gt;Grants?&lt;/h3&gt; 
Privileges on utility packages is a neutral concern. Often utilities won&#39;t be used outside the owning schema. In cases where we do need to make them more widely available we&#39;re probably granting access on some procedures that the grantee will never use.   
&lt;h3&gt;Modularity?&lt;/h3&gt;  
From an architectural perspective, modularity is the prime benefit of cohesion. A well-designed library should be frictionless and painless to navigate. The problem with random assemblages like &lt;code&gt;DBMS_UTILITY&lt;/code&gt; is that it&#39;s not obvious what functions it may contain. Sometimes we write a piece of code we didn&#39;t need to.
&lt;H2&gt;The costs of utility packages&lt;/H2&gt;
Perhaps your PL/SQL code base has a procedure like this: 
&lt;pre&gt;
create or replace procedure run_ddl
  ( p_stmt in varchar2)
is
  pragma autonomous_transaction;
  v_cursor number := dbms_sql.open_cursor;
  n pls_integer;
begin
  dbms_sql.parse(v_cursor, p_stmt, dbms_sql.native);
  n := dbms_sql.execute(v_cursor);
  dbms_sql.close_cursor(v_cursor);
exception
  when others then
    if dbms_sql.is_open(v_cursor) then
      dbms_sql.close_cursor(v_cursor);
    end if;
    raise;
end run_ddl;
/
&lt;/pre&gt;
&lt;br/&gt;
It is a nice piece of code for executing DDL statements. The autonomous_transaction pragma prevents the execution of arbitrary DML statements (by throwing &lt;code&gt;ORA-06519&lt;/code&gt;), so it&#39;s quite safe. The only problem is, it re-implements &lt;code&gt;DBMS_UTILITY.EXEC_DDL_STATEMENT()&lt;/code&gt;.
&lt;p&gt;&lt;br/&gt;
Code duplication like this is a common side effect of utility packages. Discovery is hard because their program units are clumped together accidentally. Nobody sets out to deliberately re-write &lt;code&gt;DBMS_UTILITY.EXEC_DDL_STATEMENT()&lt;/code&gt;, it happens because not enough people know to look in that package before they start coding a helper function. Redundant code is a nasty cost of Coincidental Cohesion. Besides the initial wasted effort of writing an unnecessary program there are the incurred costs of maintaining it, testing it, the risk of introducing bugs or security holes. Plus each additional duplicated program makes our code base a little harder to navigate.
&lt;p&gt;&lt;br/&gt;
Fortunately there are tactics for avoiding or dealing with this. Find out more.
&lt;p&gt;&lt;br/&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/8524462704033273745/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/8524462704033273745' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/8524462704033273745'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/8524462704033273745'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2017/05/utilities-coincidental-cohesion-anti.html' title='Utilities - the Coincidental Cohesion anti-pattern '/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-6305091156662406181</id><published>2016-12-05T05:48:00.000-08:00</published><updated>2016-12-06T00:39:50.580-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Conference"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="UKOUG2016"/><title type='text'>UKOUG Tech 2016 - Super Sunday</title><content type='html'>UKOUG 2016 is underway. This year I&#39;m staying at the Jury&#39;s Inn hotel, one of a clutch of hotels within a stone&#39;s throw of the ICC and all the action of Brindley Place. Proximity is the greatest luxury. My room is on the thirteenth floor, so I have a great view across Birmingham; a view, which &lt;a href=&quot;https://www.youtube.com/watch?v=EoHVO1eSMFc&quot; alt=&quot;Telly Savalas Looks at Birmingham&quot;&gt;in the words of Telly Savalas&lt;/a&gt; &quot;almost takes your breath away&quot;. 
&lt;br/&gt;&lt;br/&gt;
Although the conference proper - with keynotes, exhibition hall and so on - opens today, Monday, the pre-conference Super Sunday has already delivered some cracking talks. For the second year on the trot we have had a stream devoted to database development, which is great for Old Skool developers like me.
&lt;h2&gt;Fighting Bad PL/SQL, Phillip Salvisberg&lt;/h2&gt; 
The first talk in the stream discussed various metrics for assessing the the quality of PL/SQL code: McCabe Cyclic Complexity, Halstead Volume, Maintainability Index. Cyclic Complexity evaluates the number of paths through a piece of code; the more paths the harder it is to understand what the code does under any given circumstance. The volume approach assesses information density (the number of distinct words/total number of words); a higher number means more concepts, and so more to understand. The Maintainability Index takes both measures and throws it some extra calculations based on LoC and comments. 
&lt;br/&gt;&lt;br/&gt;
All these measures are interesting, and often insights but none are wholly satisfactory. Phillip showed how easier it is to game the MI by putting all the code of a function on a single line: the idea that such a layout makes our code more maintainable is laughable. More worryingly, none of these measures evaluate what the code actually does. The presented example of better PL/SQL (according to the MI measure) replaced several lines of PL/SQL into a single REGEXP_LIKE call. Regular expressions are notorious for getting  complicated and hard to maintain. Also there are performance considerations. Metrics won&#39;t replace wise human judgement just yet. In the end I agree with Phillip that the most useful metric remains &lt;i&gt;WTFs per minute&lt;/i&gt;. 
&lt;h2&gt;REST enabling Oracle tables with Oracle REST Data Services, Jeff Smith&lt;/h2&gt;
It was standing room only for That Jeff Smith, who coped well with jetlag and sleep deprivation. ORDS is the new name for the APEX listener, a misleading name because it is used for more than just APEX calls, and APEX doesn&#39;t need it. ORDS is a Java application which brokers JSON calls between a web client and the database: going one way it converts JSON payload into SQL statements, going the other way it converts result sets into JSON messages. Apparently Oracle is going to REST enable the entire database - Jeff showed us the set of REST commands for managing DataGuard. ORDS is the backbone of Oracle Cloud.
&lt;br/&gt;&lt;br/&gt;
Most of the talk centred on Oracle&#39;s capabilities for auto-enabling REST access to tables (and PL/SQL with the next release of ORDS). This is quite impressive and certainly I can see the appeal of standing up a REST web service to the database without all the tedious pfaffing in Hibernate or whatever Java framework is in place. However I think auto-enabling is the wrong approach. REST calls are stateless and cannot be assembled to form transactions; basically each one auto-commits. It&#39;s Table APIs all over again. TAPI 2.0, if you will. It&#39;s a recipe for bad applications.
&lt;br/&gt;&lt;br/&gt;
But I definitely like this vision of the future: an MVC implementation with JavaScript clients (V) passing JSON payloads to ORDS (C) with PL/SQL APIs doing all the business logic (M). The nineties revival starts here.
&lt;h2&gt;Meet your match: advanced row pattern matching, Stew Ashton&lt;/h2&gt;
Stew&#39;s talk was one of those ones which are hard to pull off: Oracle 12c&#39;s MATCH RECOGNIZE clause is a topic more suited to an article with a database on hand so we can work through the examples. Stew succeeded in making it work as a talk because he&#39;s a good speaker with a nice style and a knack for lucid explanation. He made a very good case for the importance of understanding this arcane new syntax. 
&lt;br/&gt;&lt;br/&gt;
MATCH RECOGNIZE is lifted from event processing. It allows us to define arbitrary sets of data which we can iterate over in a SELECT statement. This allows us to solve several classes of problems relating to bin filtering, positive and negative sequencing, and hierarchical summaries. The most impressive example showed how to code an inequality (i.e. range) join that performs as well as an equality join. I will certainly be downloading this presentation and learning the syntax when I get back home. 
&lt;br/&gt;&lt;br/&gt;
If only Stew had done a talk on the MODEL clause several years ago.
&lt;h2&gt;SQL for change history with Temporal Validity and Flash Back Data Archive, Chris Saxon&lt;/h2&gt;
Chris Saxon tackled the tricky concept of time travel in the database, as a mechanism for handling change. The first type of change is change in transactional data. For instance, when a customer moves house we need to retain a record of their former address as well as their new one. We&#39;ve all implemented history like this, with START_DATE and END_DATE columns. The snag has always been how to formulate the query to establish which record applies at a given point in time. Oracle 12C solves this with Temporal Validity, a syntax for defining a PERIOD using those start and end dates. Then we can query the history using a simple AS OF PERIOD clause. It doesn&#39;t solve all the problems in this area (primary keys remain tricky) but at least the queries are solved.
&lt;br/&gt;&lt;br/&gt;
The other type of change is change in metadata: when was a particular change applied? what are all the states of a record over the last year? etc. These are familiar auditing requirements, which are usually addressed through triggers and journalling tables. That approach carries an ongoing burden of maintenance and is too easy to get wrong. Oracle has had a built-in solution for several years now, Flashback Data Archive. Not enough people use it, probably because in 11g it was called Total Recall and a chargeable extra. In 12C Flashback Data Archive is free; shorn of the data optimization (which requires the Advanced Compression package) it is available in Standard Edition not just Enterprise. And it&#39;s been back-ported to 11.2.0.4. The syntax is simple: to get a historical version of the data we simply use AS OF TIMESTAMP. No separate query for a journalling table, no more nasty triggers to maintain... I honestly don&#39;t know why everybody isn&#39;t using it. 
&lt;br/&gt;&lt;br/&gt;
So that was Super Sunday. Roll on Not-So-Mundane Monday.</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/6305091156662406181/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/6305091156662406181' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/6305091156662406181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/6305091156662406181'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/12/ukoug-tech-2016-super-sunday.html' title='UKOUG Tech 2016 - Super Sunday'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-1954136524673184447</id><published>2016-11-24T00:19:00.001-08:00</published><updated>2016-11-24T00:19:52.378-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Conference"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="UKOUG"/><category scheme="http://www.blogger.com/atom/ns#" term="UKOUG2016"/><title type='text'>UKOUG Conference 2016 coming up fast</title><content type='html'>The weather has turned cold, the lights are twinkling in windows and Starbucks is selling pumpkin lattes. Yes, it&#39;s starting to look a lot like Christmas. But first there&#39;s the wonder-filled advent calendar that is the UKOUG Annual Conference in Birmingham, UK. So many doors to choose from! 
&lt;p&gt;
The Conference is the premier event for Oracle users in the UK (and beyond). This year has another cracker of an agenda: &lt;a href=&quot;http://tech16.ukoug.org/default.asp?p=14624&quot; alt=&quot;UKOUG Tech 16 Agenda home page&quot;&gt;check it out&lt;/a&gt;.  
&lt;p&gt;
The session I&#39;m anticipating most is Monday&#39;s double header with Bryn Llewellyn and Toon Koopelaar&#39;s &lt;a href=&quot;http://www.tech16.ukoug.org/default.asp?p=14778&amp;dlgact=shwprs&amp;prs_prsid=12137&amp;day_dayid=108&quot;&gt;A Real-World Comparison of the NoPLSQL &amp; Thick Database Paradigms&lt;/a&gt;.  Will they come down on the side of implementing business logic in stored procedures or won&#39;t they? It&#39;ll be tense :) But it will definitely be insightful and elegantly argued.
&lt;p&gt;
Oracle&#39;s bailiwick has expanded vastly over the years, and it&#39;s become increasingly hard to cover everything. Even so, it&#39;s fair to say in recent years older technologies such as Forms have been neglected in favour in favour of shinier baubles. Not this year. There&#39;s a good representation of Forms sessions this year, including &lt;a href=&quot;http://www.tech16.ukoug.org/default.asp?p=14778&amp;dlgact=shwprs&amp;prs_prsid=12140&amp;day_dayid=102&quot;&gt;a talk from Michael Ferrante, the Forms Product Manager&lt;/a&gt;. These sessions are all scheduled for the Wednesday, in a day targeted at database developers. If you&#39;re an Old Skool developer, especially if you&#39;re a Forms developer, and your boss will allow you only one day at the conference, then &lt;a href=&quot;http://www.tech16.ukoug.org/default.asp?p=14778&quot;&gt;Wednesday is the day to pick&lt;/a&gt;.
&lt;p&gt;
Hope to see you there</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/1954136524673184447/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/1954136524673184447' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/1954136524673184447'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/1954136524673184447'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/11/ukoug-conference-2016-coming-up-fast.html' title='UKOUG Conference 2016 coming up fast'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-5886845376765534065</id><published>2016-04-19T23:53:00.000-07:00</published><updated>2016-04-19T23:56:23.713-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="software architecture"/><title type='text'>The importance of cohesion</title><content type='html'>&quot;&lt;i&gt;Come on, come on, let&#39;s stick together&lt;/i&gt;&quot; - Bryan Ferry&lt;br /&gt;
&lt;br /&gt;
There&#39;s more to PL/SQL programs than packages, but most of our code will live in packages. The &lt;a href=&quot;https://docs.oracle.com/database/121/LNPLS/packages.htm#LNPLS00904&quot; alt=&quot;12c PL/SQL Reference&quot;&gt;PL/SQL Reference offers&lt;/a&gt; the following benefits of organising our code into packages:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Modularity&lt;/b&gt; - we encapsulate logically related components into an easy to understand structure.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Easier Application Design&lt;/b&gt; - we can start with the interface in the package specification and code the implementation later.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Hidden Implementation Details &lt;/b&gt;- the package body is private so we can prevent application users having direct access to certain functionality.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Added Functionality&lt;/b&gt; - we can share the state of Package public variables and cursors for the life of a session.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Better Performance&lt;/b&gt; - Oracle Database loads the whole package into memory the first time you invoke a package subprogram, which makes subsequent invocations of any other subprogram quicker. Also packages prevent cascading dependencies and unnecessary recompilation.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Grants&lt;/b&gt; - we can grant permission on a single package instead of a whole bunch of objects.&lt;br /&gt;
&lt;br /&gt;
However, we can only realise these benefits if the packaged components belong together: in other words, if our package is cohesive. &amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
The &lt;a href=&quot;https://en.wikipedia.org/wiki/Cohesion_(computer_science)&quot;&gt;ever reliable Wikipedia defines cohesion &lt;/a&gt;like this: &quot;t&lt;i&gt;he degree to which the elements of a module belong together&quot;&lt;/i&gt;; in other words how it&#39;s a measure of the strength of the relationship between components. It&#39;s common to think of cohesion as a binary state - either a package is cohesive or it isn&#39;t - but actually it&#39;s a spectrum. (Perhaps computer science should use &amp;nbsp;&quot;cohesiveness&quot; which is more expressi but cohesion it is.)&lt;br /&gt;
&lt;h3&gt;
Cohesion&lt;/h3&gt;
Cohesion owes its origin as a Comp Sci term to &lt;a href=&quot;http://dl.acm.org/citation.cfm?id=1661068&quot; alt=&quot;Structured Design&quot;&gt;Stevens, Myers, and Constantine&lt;/a&gt;. &amp;nbsp;Back in the Seventies they used the terms &quot;module&quot; and &quot;processing elements&quot;, but we&#39;re discussing PL/SQL so let&#39;s use Package and Procedure instead. They defined seven levels of cohesion, with each level being better - more usefully cohesive - than its predecessor.&lt;br /&gt;
&lt;h4&gt;
Coincidental&lt;/h4&gt;
The package comprises an arbitrary selection of procedures and functions which are not related in any way. This obviously seems like a daft thing to do, but most packages with &quot;Utility&quot; in their name fall into this category. &lt;br /&gt;
&lt;h4&gt;
Logical&lt;/h4&gt;
The package contains procedures which all belong to the same logical class of functions. For instance, we might have a package to collect all the procedures which act as endpoints for REST Data Services.&lt;br /&gt;
&lt;h4&gt;
Temporal&lt;/h4&gt;
The package consists of procedures which are executed at the same system event. So we might have a package of procedures executed when a user logs on - authentication, auditing, session initialisation - and similar package for tidying up when the user logs off. Other than the triggering event the packaged functions are unrelated to each other.&lt;br /&gt;
&lt;h4&gt;
Procedural&lt;/h4&gt;
The package consists of procedures which are executed as part of the same business event. For instance, in an auction application there are a set of actions to follow whenever a bid is made: compare to asking price, evaluate against existing maximum bid, update lot&#39;s status, update bidder&#39;s history, send an email to the bidder, send an email to the user who&#39;s been outbid, etc.&lt;br /&gt;
&lt;h4&gt;
Communicational&lt;/h4&gt;
The package contains procedures which share common inputs or outputs. For example a payroll package may have procedures to calculate base salary, overtime, sick pay, commission, bonuses and produce the overall remuneration for an employee.&lt;br /&gt;
&lt;h4&gt;
Sequential&lt;/h4&gt;
The package comprises procedures which are executed as a chain, so that the output of one procedure becomes the input for another procedure. A classic example of this is an ETL package with procedures for loading data into a staging area, validating and transforming the data, and then loading records into the target table(s).&lt;br /&gt;
&lt;h4&gt;
Functional&lt;/h4&gt;
The package comprises procedures which are focused on a single task. Not only are all the procedures strongly related to each other but they are fitted to user roles too. So procedures for power users are in a separate package from procedures for normal users. The Oracle built-in packages for Advanced Queuing are a good model of Functional cohesion. &lt;br /&gt;
&lt;h3&gt;
How cohesive is cohesive enough?&lt;/h3&gt;
The grades of cohesion, with Coincidental as the worst and Functional as the best, are guidelines. Not every package needs to have Functional cohesion. In a software architecture we will have modules at different levels. The higher modules will tend to be composed of calls to lower level modules. The low level modules are the concrete implementations and they should aspire to Sequential or Functional cohesion.&lt;br /&gt;
&lt;br /&gt;
The higher level modules can be organised to other levels. For instance we might want to build packages around user roles - Sales, Production, HR, IT - because Procedural cohesion makes it easier for the UI teams to develop screens, especially if they need to skin them for various different technologies (desktop, web, mobile). Likewise we wouldn&#39;t want to have Temporally cohesive packages with concrete code for managing user logon or logoff. But there is a value in organising a package which bundles up all the low level calls into a single abstract call for use in schema level AFTER LOGON triggers. &amp;nbsp; &amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Cohesion is not an easily evaluated condition. We need cohesion with a purpose, a reason to stick those procedures together. It&#39;s not enough to say &quot;this package is cohesive&quot;. We must take into consideration how cohesive the package needs to be: how will it be used? what is its relationships with the other packages?&lt;br /&gt;
&lt;br /&gt;
Applying design principles such as Single Responsibility, Common Reuse, Common Closure and Interface Segregation can help us to build cohesive packages. Getting the balance right requires an understanding of the purpose of the package and its place within the overall software architecture. &amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
&lt;hl/&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/5886845376765534065/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/5886845376765534065' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/5886845376765534065'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/5886845376765534065'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/04/the-importance-of-cohesion.html' title='The importance of cohesion'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-8744862240808391902</id><published>2016-04-03T10:55:00.002-07:00</published><updated>2016-04-03T10:55:58.515-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="principles"/><title type='text'>Working with the Interface Segregation Principle</title><content type='html'>Obviously Interface Segregation is crucial for implementing restricted access. For any given set of data there are three broad categories of access:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;reporting&amp;nbsp;&lt;/li&gt;
&lt;li&gt;manipulation&amp;nbsp;&lt;/li&gt;
&lt;li&gt;administration and governance&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
So we need to define at least one interface - packages - for each category in order that we can grant the appropriate access to different groups of users: read-only users, regular users, power users.&lt;br /&gt;
&lt;br /&gt;
But there&#39;s more to Interface Segregation. This example is based on a procedure posted on a programming forum. Its purpose is to maintain medical records relating to a patient&#39;s drug treatments. The procedure has some business logic (which I&#39;ve redacted) but its overall structure is defined by the split between the Verification task and the De-verification task, and flow is controlled by the value of the &lt;code&gt;p_verify_mode parameter&lt;/code&gt;.
&lt;br /&gt;
&lt;pre&gt; 
procedure rx_verification
     (p_drh_id in number,
       p_patient_name in varchar2,
       p_verify_mode in varchar2)
as
    new_rxh_id number;
    rxh_count number;
    rxl_count number;
    drh_rec drug_admin_history%rowtype;
begin
    select * into drh_rec ....;
    select count(*) into rxh_count ....;

    if p_verify_mode = &#39;VERIFY&#39; then

        update drug_admin_history ....;
        if drh_rec.pp_id &amp;lt;&amp;gt; 0 then
            update patient_prescription ....;
        end if;
        if rxh_count = 0 then
            insert into prescription_header ....;
        else
            select rxh_id into new_rxh_id ....;
        end if;
        insert into prescription_line ....;
        if drh_rec.threshhold &amp;gt; 0
            insert into prescription_line ....;
        end if;

    elsif p_verify_mode = &#39;DEVERIFY&#39; then

        update drug_admin_history ....;
        if drh_rec.pp_id &amp;lt;&amp;gt; 0 then
            update patient_prescription ....;
        end if;
        select rxl_rxh_id into new_rxh_id ....;
        delete prescription_line ....;
        delete prescription_header ....;

    end if;
end;
&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
Does this procedure have a Single Responsibility?  Hmmm. It conforms to Common Reuse - users who can verify can also de-verify. It doesn&#39;t break Common Closure, because both tasks work with the same tables. But there is a nagging doubt. It appears to be doing two things: Verification and De-verification.&lt;br /&gt;
&lt;br /&gt;
So, how does this does this procedure work as an interface? There is a definite problem when it comes to calling the procedure: how do I as a developer know what value to pass to &lt;code&gt;p_verify_mode&lt;/code&gt;?

&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;  rx_management.rx_verification
     (p_drh_id =&amp;gt; 1234,
       p_patient_name =&amp;gt; &#39;John Yaya&#39;,
       p_verify_mode =&amp;gt; ???);
&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
The only way to know is to inspect the source code of the procedure. That breaks the Information Hiding principle, and it might not be viable (if the procedure is owned by a different schema). Clearly the interface could benefit from a redesign. One approach would be to declare constants for the acceptable values; while we&#39;re at it, why not define a PL/SQL subtype for verification mode and tweak the procedure&#39;s signature to make it clear that&#39;s what&#39;s expected:        
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;create or replace package rx_management is
 
  subtype verification_mode_subt is varchar2(10);
  c_verify constant verification_mode_subt := &#39;VERIFY&#39;; 
  c_deverify constant verification_mode_subt := &#39;DEVERIFY&#39;; 
 
  procedure rx_verification
     (p_drh_id in number,
       p_patient_name in varchar2,
       p_verify_mode in verification_mode_subt);

end rx_management;
&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
Nevertheless it is still possible for a caller program to pass a wrong value:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;  rx_management.rx_verification
     (p_drh_id =&amp;gt; 1234,
       p_patient_name =&amp;gt; &#39;John Yaya&#39;,
       p_verify_mode =&amp;gt; &#39;Verify&#39;);
&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
What happens then? Literally nothing. The value drops through the control structure without satisfying any condition. It&#39;s an unsatisfactory outcome. We could change the implementation of &lt;code&gt;rx_verification()&lt;/code&gt; to validate the parameter value and raise and exception. Or we could add an &lt;code&gt;ELSE&lt;/code&gt; branch and raise an exception. But those are runtime exceptions. It would be better to mistake-proof the interface so that it is not possible to pass an invalid value in the first place.&lt;br /&gt;
&lt;br /&gt;
Which leads us to to a Segregated Interface :
&lt;br /&gt;
&lt;pre&gt;&lt;/pre&gt;
&lt;pre&gt;create or replace package rx_management is
 
  procedure rx_verification
     (p_drh_id in number,
       p_patient_name in varchar2);
 
  procedure rx_deverification
     (p_drh_id in number);
     
end rx_management;
&lt;/pre&gt;
&lt;pre&gt;&lt;/pre&gt;
Suddenly it becomes clear that the original procedure was poorly named (I call &lt;code&gt;rx_verification()&lt;/code&gt; to issue an RX de-verification?!)  We have two procedures but their usage is now straightforward and the signatures are cleaner (the &lt;code&gt;p_patient_name&lt;/code&gt; is only used in the Verification branch so there&#39;s no need to pass it when issuing a De-verification).&lt;br /&gt;
&lt;h3&gt;
Summary&lt;/h3&gt;
Interface Segregation creates simpler and safer controls but more of them. This is a general effect of the Information Hiding principle. It is a trade-off. We need to be sensible. Also, this is not a proscription against flags. There will always be times when we need to pass instructions to called procedures to modify their behaviour. In those cases it is important that the interface includes a definition of acceptable values. 

&lt;br /&gt;
&lt;hl&gt;
&lt;/hl&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/8744862240808391902/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/8744862240808391902' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/8744862240808391902'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/8744862240808391902'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/04/working-with-interface-segregation.html' title='Working with the Interface Segregation Principle'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-3630259531958940091</id><published>2016-04-03T10:55:00.001-07:00</published><updated>2016-04-03T11:00:25.850-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="principles"/><title type='text'>Three more principles</title><content type='html'>Here are some more principles which can help us design better programs. These principles aren&#39;t part of an organized theory, and they&#39;re aren&#39;t particularly related to any programming paradigm. But each is part of the canon, and each is about the relationship between a program&#39;s interface and its implementation.&lt;br /&gt;
&lt;h4&gt;
The Principle Of Least Astonishment&lt;/h4&gt;
Also &lt;a alt=&quot;Wikipedia&quot; href=&quot;https://en.wikipedia.org/wiki/Principle_of_least_astonishment&quot;&gt;known as the Principle of Least Surprise&lt;/a&gt;, the rule is simple: programs should do what we expect them to do. This is more than simply honouring the contract of the interface. It means complying with accepted conventions of our programming. In PL/SQL programming there is a convention that functions are read-only, or at least do not change database state. Another such convention is that low-level routines do not execute &lt;code&gt;COMMIT&lt;/code&gt; statements; transaction management is the prerogative of the program at the top of the call stack, which may be interacting directly with a user or may be an autonomous batch process.&lt;br /&gt;
&lt;br /&gt;
Perhaps the most common flouting of the Principle Of Least Astonishment is this:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;   exception
      when others then
      null; 
&lt;/pre&gt;
&lt;br /&gt;
It is reasonable to expect that a program will hurl an exception if something as gone awry. Unfortunately, we are not as astonished as we should be when we find a procedure with an exception handle which swallows any and every exception.&lt;br /&gt;
&lt;h4&gt;
Information Hiding Principle&amp;nbsp;&lt;/h4&gt;
Another venerable principle, this one was expounded by &lt;a alt=&quot;c2 wiki&quot; href=&quot;http://c2.com/cgi/wiki/wiki?InformationHiding&quot;&gt;David Parnas in 1972&lt;/a&gt;. It requires that a calling program should not need to know anything about the implementation of a called program. The definition of the interface should be sufficient. It is the cornerstone of black-box programming. The virtue of Information Hiding is that knowledge of internal details inevitably leads to coupling between the called and calling routines: when we change the called program we need to change the caller too. We honour this principle any time we call a procedure in a package owned by another schema, because the &lt;code&gt;EXECUTE&lt;/code&gt; privilege grants visibility of the package specification (the interface) but not the body (the implementation).&lt;br /&gt;
&lt;h4&gt;
The Law Of Leaky Abstractions&lt;/h4&gt;
&lt;a alt=&quot;Joel on Software&quot; href=&quot;http://www.joelonsoftware.com/articles/LeakyAbstractions.html&quot;&gt;Joel Spolsky coined this one&lt;/a&gt;: &quot;All non-trivial abstractions, to some degree, are leaky.&quot; No matter how hard we try, some details of the implementation of a called program will be exposed to the calling programming, and will need to be acknowledged. Let&#39;s consider this interface again:
&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;    function get_employee_recs
        ( p_deptno in number ) 
        return emp_refcursor;
&lt;/pre&gt;
&lt;br /&gt;
We know it returns a result set of employee records. But in what order? Sorting by &lt;code&gt;EMPNO&lt;/code&gt; would be pretty useless, given that it is a surrogate key (and hence without meaning). Other candidates - &lt;code&gt;HIREDATE&lt;/code&gt;, &lt;code&gt;SAL&lt;/code&gt; - will be helpful for some cases and irrelevant for others. One approach is to always return an unsorted set and leave it to the caller to sort the results; but it is usually more efficient to sort records in a query rather than a collection. Another approach would be to write several functions - &lt;code&gt;get_employee_recs_sorted_hiredate()&lt;/code&gt;, &lt;code&gt;get_employee_recs_sorted_sal()&lt;/code&gt; - but that leads to a bloated interface which is hard to understand. Tricky.&lt;br /&gt;
&lt;h4&gt;
Conclusion&lt;/h4&gt;
Principles are guidelines. There are tensions between them. Good design is a matter of trade-offs. We cannot blindly follow Information Hiding and ignore the Leaky Abstractions. We need to exercise our professional judgement (which is a good thing). 

&lt;br /&gt;
&lt;hl&gt;
&lt;/hl&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/3630259531958940091/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/3630259531958940091' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/3630259531958940091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/3630259531958940091'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/04/three-more-principles.html' title='Three more principles'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-7840654030260585895</id><published>2016-04-03T10:55:00.000-07:00</published><updated>2016-04-03T10:59:28.606-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="interfaces"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><title type='text'>It&#39;s all about the interface </title><content type='html'>When we talk about program design we&#39;re mainly talking about interface design. The interface is the part of our program that the users interact with. Normally discussion of UI focuses on GUI or UX, that is, the interface with the end user of our application.&lt;br /&gt;
&lt;br /&gt;
But developers are users too.&lt;br /&gt;
&lt;br /&gt;
Another developer writing a program which calls a routine in my program is a user of my code (and, I must remember, six months after I last touched the program, I am that other developer). A well-designed interface is frictionless: it can be slotted into a calling program without too much effort. A poor interface breaks the flow: it takes time and thought to figure it out. In the worst case we have to scramble around in the documentation or the source code.&lt;br /&gt;
&lt;br /&gt;
Formally, an interface is the mechanism which allows the environment (the user or agent) to interact with the system (the program). What the system actually does is the implementation: the interface provides access to the implementation without the environment needing to understand the details. In PL/SQL programs the implementation will usually contain a hefty chunk of SQL. The interface mediates access to data.&lt;br /&gt;
&lt;br /&gt;
An interface is a contract. It specifies what the caller must do and what the called program will do in return. Take this example:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;function get_employee_recs
&amp;nbsp; &amp;nbsp; &amp;nbsp;( p_deptno in number )
&amp;nbsp; &amp;nbsp; &amp;nbsp;return emp_refcursor;

&lt;/pre&gt;
The contract says, if the calling program passes a valid &lt;code&gt;DEPTNO&lt;/code&gt; the function will return records for all the employees in that department, as a strongly-typed ref cursor. Unfortunately the contract doesn&#39;t say what will happen if the calling program passes an invalid &lt;code&gt;DEPTNO&lt;/code&gt;. Does the function return an empty set or throw an exception? The short answer is we can&#39;t tell. We must rely on convention or the document, which is an unfortunate gap in the PL/SQL language; the Java keyword &lt;code&gt;throws&lt;/code&gt; is quite neat in this respect.&lt;br /&gt;
&lt;h3&gt;
The interface is here to help&lt;/h3&gt;
The interface presents an implementation of business logic. The interface is a curated interpretation, and doesn&#39;t enable unfettered access. Rather, a well-designed interface helps a developer use the business logic in a sensible fashion. Dan Lockton calls this &lt;a alt=&quot;Architectures&quot; href=&quot;http://architectures.danlockton.co.uk/simple-control-in-products&quot;&gt;Design With Intent&lt;/a&gt;: Good design expresses how a product should be used. It doesn&#39;t have to be complicated. We can use simple control mechanisms which to help other developers use our code properly.&lt;br /&gt;
&lt;h4&gt;
Restriction of access&lt;/h4&gt;
Simply, the interface restricts access to certain functions or denies it altogether. Only certain users are allowed to view salaries, and even fewer to modify them. The interface to Employee records should separate salary functions from more widely-available functions. Access restriction can be implemented in a hard fashion, using architectural constructs (views, packages, schemas) or in a soft fashion (using VPD or Data Vault). The hard approach benefits from clarity, the soft approach offers flexibility.&lt;br /&gt;
&lt;h4&gt;
Forcing functions&lt;/h4&gt;
If certain things must be done in a specific order then the interface should only offer a method which enforces the correct order. For instance, if we need to insert records into a parent table and a child table in the same transaction (perhaps a super-type/sub-type implementation of a foreign key arc) a helpful interface will only expose a procedure which inserts both records in the correct order.&lt;br /&gt;
&lt;h4&gt;
Mistake-proofing&lt;/h4&gt;
A well-design interface prevents its users from making obvious mistakes. The signature of a procedure should be clear and unambiguous. Naming is important. If a parameter presents a table attribute the parameter name should echo the column name: &lt;code&gt;p_empno&lt;/code&gt; is better than &lt;code&gt;p_id&lt;/code&gt;. Default values for parameters should lead developers to sensible and safe choices. If several parameters have default values they must play nicely together: accepting all the defaults should not generate an error condition.&lt;br /&gt;
&lt;h3&gt;
Abstraction&lt;/h3&gt;
Abstraction is just another word for interface. It allows us to focus on the details of our own code without need to understand the concrete details of the other code we depend upon. That&#39;s why good interfaces are the key to managing large codebases.
&lt;br /&gt;
&lt;hl&gt;
&lt;/hl&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/7840654030260585895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/7840654030260585895' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/7840654030260585895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/7840654030260585895'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/04/its-all-about-interface.html' title='It&#39;s all about the interface '/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-5164350992784075658</id><published>2016-03-16T16:43:00.002-07:00</published><updated>2020-09-16T07:38:22.082-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="interfaces"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="principles"/><category scheme="http://www.blogger.com/atom/ns#" term="software architecture"/><title type='text'>Designing PL/SQL Programs: Series home page</title><content type='html'>Designing PL/SQL Programs is a succession of articles published the articles in a nonlinear fashion.  Eventually it will evolve into a coherent series.  In the meantime this page serves as a map and navigation aid.  I will add articles to it as and when I publish them.

&lt;br /&gt;
&lt;h2&gt;
Introduction&lt;/h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs.html&quot;&gt;Designing PL/SQL Programs&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/04/its-all-about-interface.html&quot;&gt;It&#39;s all about the interface&lt;/a&gt;&lt;br /&gt;
&lt;h2&gt;
Principles and Patterns&lt;/h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/introducing-solid-design-principles.html&quot;&gt;Introducing the SOLID principles&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/introducing-rccass-design-principles.html&quot;&gt;Introducing the RCCASS principles&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/04/three-more-principles.html&quot;&gt;Three more principles&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://radiofreetooting.blogspot.com/2018/05/the-single-responsibility-principle.html&quot;&gt;The Single Responsibility principles&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/the-dependency-inversion-principle.html&quot;&gt;The Dependency Inversion Principle: a practical example&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/04/working-with-interface-segregation.html&quot;&gt;Working with the Interface Segregation Principle&lt;/a&gt;

&lt;h2&gt;
Software Architecture&lt;/h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/04/the-importance-of-cohesion.html&quot;&gt;The importance of cohesion&lt;/a&gt;&lt;br/&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2017/05/utilities-coincidental-cohesion-anti.html&quot;&gt;Utilities - the Coincidental Cohesion anti-pattern&lt;/a&gt;&lt;br/&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2017/05/avoiding-coincidental-cohesion.html&quot;&gt;Avoiding Coincidental Cohesion&lt;/a&gt;
&lt;h2&gt;
Interface design&lt;/h2&gt;
&lt;a href=&quot;hhttps://radiofreetooting.blogspot.com/2017/12/data-access-layer-vs-table-apis.html&quot;&gt;Data Access Layer versus Table APIs&lt;/a&gt;
&lt;a href=&quot;https://radiofreetooting.blogspot.com/2020/09/the-use-and-misuse-of-type-and-rowtype.html&quot;&gt;The use and misuse of &lt;code&gt;%TYPE&lt;/code&gt; and &lt;code&gt;%ROWTYPE&lt;/code&gt; attributes in PL/SQL APIs&lt;/a&gt;
&lt;h2&gt;
Tools and Techniques&lt;/h2&gt;</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/5164350992784075658/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/5164350992784075658' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/5164350992784075658'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/5164350992784075658'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html' title='Designing PL/SQL Programs: Series home page'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-2242191084717473442</id><published>2016-03-16T01:04:00.000-07:00</published><updated>2016-04-03T10:54:37.389-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="principles"/><title type='text'>The Dependency Inversion Principle: a practical example</title><content type='html'>These design principles may seem rather academic, so let&#39;s look at a real life demonstration of how applying Dependency Inversion Principle lead to an improved software design. 
&lt;br /&gt;
&lt;br /&gt;
Here is a simplified version of an ETL framework which uses SQL Types in a similar fashion to the approach described in &lt;a alt=&quot;Programming with Oracle SQL TYPE constructs, Part 2&quot; href=&quot;http://radiofreetooting.blogspot.com/2006/12/programming-with-oracle-sql-type.html&quot;&gt;my blog post here&lt;/a&gt;. The loading process is defined using an abstract non-instantiable Type like this:&lt;br /&gt;
&lt;pre&gt;create or replace type load_t force as object
    ( txn_date date
      , tgt_name varchar2(30)
      , member function load return number
      , final member function get_tgt return varchar2
      )
not final not instantiable;
/

create or replace type body load_t as
    member function load return number
    is
    begin
        return 0;
    end load;
    final member function get_tgt return varchar2
    is
    begin
        return self.tgt_name;
    end get_tgt;
end;
/

&lt;/pre&gt;
&lt;br /&gt;
The concrete behaviour for each target table in the ABC feed is defined by sub-types like this: 
&lt;br /&gt;
&lt;pre&gt;create or replace type load_tgt1_t under load_t
    ( overriding member function load return number
        , constructor function load_tgt1_t
            (self in out nocopy load_tgt1_t
             , txn_date date)
           return self as result
      )
;
/
create or replace type body load_tgt1_t as
    overriding member function load return number
    is
    begin
        insert into tgt1 (col1, col2)
        select to_number(col_a), col_b
        from stg_abc stg
        where stg.txn_date = self.txn_date;
        return sql%rowcount;
    end load;
    constructor function load_tgt1_t
            (self in out nocopy load_tgt1_t
             , txn_date date)
           return self as result
    is
    begin
        self.txn_date := txn_date;
        self.tgt_name := &#39;TGT1&#39;;
        return;
    end load_tgt1_t;
end;
/
&lt;/pre&gt;
This approach is neat because ETL is a fairly generic process: the mappings and behaviour for a particular target table are specific but the shape of the loading process is the same for any and all target tables. So we can build a generic PL/SQL procedure to handle them.  This simplistic example does some logging, loops through a set of generic objects and, through the magic of polymorphism, calls a generic method which executes specific code for each target table:
&lt;br /&gt;
&lt;pre&gt;    procedure load  
     (p_txn_date in date
        , p_load_set in sys_refcursor)
    is
        type loadset_r is record (
            tgtset load_t
            );
        lrecs loadset_r;
        load_count number;
    begin
        logger.logm(&#39;LOAD START::txn_date=&#39;||to_char(p_txn_date,&#39;YYYY-MM-DD&#39;));
        loop
            fetch p_load_set into lrecs;
            exit when p_load_set%notfound;
            logger.logm(lrecs.tgtset.get_tgt()||&#39; start&#39;);
            load_count := lrecs.tgtset.load();
            logger.logm(lrecs.tgtset.get_tgt()||&#39; loaded=&#39;||to_char(load_count));
        end loop;
        logger.logm(&#39;LOAD FINISH&#39;);
    end load;

&lt;/pre&gt;
So far, so abstract. The catch is the procedure which instantiates the objects:
&lt;br /&gt;
&lt;pre&gt;    procedure load_abc_from_stg  
         (p_txn_date in date)
    is
        rc sys_refcursor;
    begin
        open rc for
            select load_tgt1_t(p_txn_date) from dual union all
            select load_tgt2_t(p_txn_date) from dual;
       load(p_txn_date, rc);
    end load_abc_from_stg;

&lt;/pre&gt;
On casual inspection it doesn&#39;t seem problematic but the call to the &lt;code&gt;load()&lt;/code&gt; procedure gives the game away. Both procedures are in the same package:
&lt;br /&gt;
&lt;pre&gt;create or replace package loader as
    procedure load 
     (p_txn_date in date
        , p_load_set in sys_refcursor);
    procedure load_abc_from_stg
         (p_txn_date in date);
end loader;
/

&lt;/pre&gt;
So the package mixes generic and concrete functionality. What makes this a problem? After all, it&#39;s all ETL so doesn&#39;t the package follow the Single Responsibility Principle? Well, up to a point. But if we want to add a new table to the ABC feed we need to update the LOADER package. Likewise if we want to add a new feed, DEF, we need to update the LOADER package. So it breaks the Stable Abstractions principle. It also creates dependency problems, because the abstract &lt;code&gt;load()&lt;/code&gt; process has dependencies on higher level modules. We can&#39;t deploy the LOADER package without deploying objects for all the feeds.
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
Applying the Dependency Inversion Principle.&lt;/h2&gt;
The solution is to extract the &lt;code&gt;load_abc()&lt;/code&gt; procedure into a concrete package of its own. To make this work we need to improve the interface between the &lt;code&gt;load()&lt;/code&gt; procedure and programs which call it.  Both sides of the interface should depend on a shared abstraction.
&lt;br /&gt;
&lt;br /&gt;
The LOADER package is now properly generic:
&lt;br /&gt;
&lt;pre&gt;create or replace package loader as
    type loadset_r is record (
            tgtset load_t
            );
    type loadset_rc is ref cursor return loadset_r;
    procedure load 
        (p_txn_date in date
          , p_load_set in loadset_rc)
         authid current_user
               ;
end loader;
/
&lt;/pre&gt;
The &lt;code&gt;loadset_r&lt;/code&gt; type has moved into the package specification, and defines a strongly-typed ref cursor. The &lt;code&gt;load()&lt;/code&gt; procedure uses the strongly-typed ref cursor. 
&lt;br /&gt;
&lt;br /&gt;
Similarly the LOAD_ABC package is wholly concrete:
&lt;br /&gt;
&lt;pre&gt;create or replace package loader_abc as
    procedure load_from_stg
            (p_txn_date in date);
end loader_abc;
/

create or replace package body loader_abc as
    procedure load_from_stg
            (p_txn_date in date)
    is
        rc loader.loadset_rc;
    begin
        open rc for
            select load_tgt1_t(p_txn_date) from dual union all
            select load_tgt2_t(p_txn_date) from dual;
       loader.load(p_txn_date, rc);
    end load_from_stg;
end loader_abc;
/
&lt;/pre&gt;
Both package bodies now depend on abstractions: the strongly-typed ref cursor in the LOADER specification and the LOADER_T SQL Type. These should change much less frequently than the tables in the feed or even the loading process itself. This is the Dependency Inversion Principle in action. 
&lt;br /&gt;
&lt;br /&gt;
Separating generic and concrete functionality into separate packages produces a more stable application. Users of a feed package are shielded from changes in other feeds. The LOADER package relies on strongly-typed abstractions. Consequently we can code a new feed package which can call &lt;code&gt;loader.load()&lt;/code&gt; without peeking into that procedure&#39;s implementation to see what it&#39;s expecting.  
&lt;br /&gt;
&lt;br /&gt;
&lt;hl&gt;
&lt;/hl&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/2242191084717473442/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/2242191084717473442' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2242191084717473442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2242191084717473442'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/03/the-dependency-inversion-principle.html' title='The Dependency Inversion Principle: a practical example'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-1048642800365142041</id><published>2016-03-15T00:46:00.002-07:00</published><updated>2016-03-15T00:46:27.609-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Humour"/><category scheme="http://www.blogger.com/atom/ns#" term="Office life"/><title type='text'>A new law of office life</title><content type='html'>I posted &lt;a href=&quot;http://radiofreetooting.blogspot.co.uk/2006/09/clarkes-three-laws-of-office-life.html&quot;&gt;my Three Laws of Office Life &lt;/a&gt;a long while back.  Subsequent experience has revealed another one: 
&lt;i&gt;Every office kitchen which has a sign reminding people to do their washing-up has a concomitant large pile of unwashed crockery and dirty cutlery.&lt;/i&gt;
&lt;br /&gt;
&lt;br /&gt;
People wash their own mug and cereal bowl, but are less rigorous with the crockery from the kitchen cupboard.  This phenomenon will be familiar to anybody who has shared a house during their student days or later.&lt;br /&gt;
&lt;br /&gt;
Don&#39;t think that installing a dishwasher will change anything: it merely transfers the problem.  Someone who won&#39;t wash up a mug is even less likely to unload a dishwasher. There is only one workable solution, and that is to have no office kitchen at all. (Although this creates a new problem, as vending machine coffee is universally vile and the tea unspeakable.)&lt;br /&gt;
&lt;br /&gt;
So the Pile of Washing Up constitutes an ineluctable law, but it is the fourth law and we all know that the canon only admits &lt;a href=&quot;http://en.wikipedia.org/wiki/Laws_of_thermodynamics&quot;&gt;sets&lt;/a&gt; &lt;a href=&quot;http://csep10.phys.utk.edu/astr161/lect/history/newton3laws.html&quot;&gt;of&lt;/a&gt; &lt;a href=&quot;http://www.auburn.edu/~vestmon/robotics.html&quot;&gt;three&lt;/a&gt; &lt;a href=&quot;http://www.threelawsofperformance.com/&quot;&gt;laws&lt;/a&gt;.  One must go.  Since I first formulated these laws cost-cutting in the enterprise has more-or-less abolished the practice of providing biscuits at meetings.  Hence the old Second Law no longer holds, and creates a neat vacancy.&lt;br /&gt;
&lt;br /&gt;
Here are the revised Laws of Office Life:
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;First law:&lt;/b&gt; For every situation there is an equal and apposite Dilbert cartoon.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Second Law:&lt;/b&gt; Every office kitchen which has a sign reminding people to do their washing-up has a concomitant large pile of unwashed crockery and dirty cutlery.
&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Third Law:&lt;/b&gt; The bloke with the most annoying laugh is the one who finds everything funny.</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/1048642800365142041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/1048642800365142041' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/1048642800365142041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/1048642800365142041'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/03/a-new-law-of-office-life.html' title='A new law of office life'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-4360730518359520997</id><published>2016-03-15T00:18:00.002-07:00</published><updated>2016-04-03T10:54:56.755-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="principles"/><title type='text'>Introducing the RCCASS design principles</title><content type='html'>Rob C Martin actually defined eleven principles for OOP. The first five, &lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/introducing-solid-design-principles.html&quot;&gt;the SOLID principles&lt;/a&gt;, relate to individual classes. The other six, the RCCASS principles, deal with the design of packages (in the C++ or Java sense, i.e. libraries). They are far less known than the first five. There are two reasons for this:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Unlike &quot;SOLID&quot;, &quot;RCCASS&quot; is awkward to say and doesn&#39;t form a neat mnemonic.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Programmers are far less interested in software architecture.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
Software architecture tends to be an alien concept in PL/SQL. Usually a codebase of packages simply accretes over the years, like a coral reef. Perhaps the RCCASS principles can help change that.&lt;br /&gt;
&lt;h2&gt;
The RCCASS Principles&lt;/h2&gt;
&lt;h3&gt;
Reuse Release Equivalency Principle&amp;nbsp;&lt;/h3&gt;
The Reuse Release Equivalency Principle states that the unit of release matches the unit of reuse, which is the parts of the program unit which are consumed by other programs. Basically the unit of release defines the scope of regression testing for consuming applications. It&#39;s an ill-mannered release which forces projects to undertake unnecessary regression testing. Cohesive program units allow consumers to do regression testing only for functionality they actually use. It&#39;s less of a problem for PL/SQL because (unlike C++ libraries of Java jars) the unit of release can have a very low level of granularity: individual packages or stored procedures.&lt;br /&gt;
&lt;h3&gt;
Common Reuse Principle&amp;nbsp;&lt;/h3&gt;
The Common Reuse principle supports the definition of cohesive program units. Functions which share a dependency belong together, because they are likely to be used together belong together. For instance, procedures which maintain the Employees table should be co-located in one package (or a group of related packages). They will share sub-routines, constants and exceptions. Packaging related procedures together makes the package easier to write and easier for calling programs to use.&lt;br /&gt;
&lt;h3&gt;
Common Closure Principle&lt;/h3&gt;
The Common Closure principle supports also the definition of cohesive program units. Functions which share a dependency belong together, because they have a common axis of change. Common Closure helps to minimise the number of program units affected by a change. For instance, programs which use the Employees table may need to change if the structure of the table changes. All the changes must be released together: table, PL/SQL, types, etc.&lt;br /&gt;
&lt;h3&gt;
Acyclic Dependencies Principle&amp;nbsp;&lt;/h3&gt;
Avoid cyclic dependencies between program units: if package A depends on package B then B must not have a dependency on B. Cyclic dependencies make application hard to use and harder to deploy. The dependency graph shows the order in which objects must be built. Designing a dependency graph upfront is futile, but we can keep to rough guidelines. Higher level packages implementing business rules tend to depend on generic routines which in turn tend to depend on low-level utilities. There should be no application logic in those lower-level routines. If SALES requires a special logging implementation then that should be handled in the SALES subsystem not in the standard logging package.&lt;br /&gt;
&lt;h3&gt;
Stable Dependencies Principle&amp;nbsp;&lt;/h3&gt;
Any change to the implementation of a program unit which is widely used will generate regression tests for all the programs which call it. At the most extreme, a change to a logging routine could affect all the other programs in our application. As with the Open/Closed Principle we need to fix bugs. But new features should be introduced by extension not modification. And refactoring of low-level dependencies must not done on a whim.&lt;br /&gt;
&lt;h3&gt;
Stable Abstractions Principle&lt;/h3&gt;
Abstractions are dependencies, especially when we&#39;re talking about PL/SQL.  So this Principle is quite similar to Stable Dependencies Principle. The key difference is that this relates to the definition of interfaces rather than implementation. A change to the signature of a logging routine could require code changes to all the other programs in the application. Obviously this is even more inconvenient than enforced regression testing. Avoid changing the signature of a public procedure or the projection of a public view. Again, extension rather than modification is the preferred approach.&lt;br /&gt;
&lt;h2&gt;
Applicability of RCCASS principles in PL/SQL&amp;nbsp;&lt;/h2&gt;
The focus of these principles is the stability of a shared codebase, and minimising the impact of change on the consumers of our code. This is vital in large projects, where communication between teams is often convoluted. It is even more important for open source or proprietary libraries.&lt;br /&gt;
&lt;br /&gt;
We we can apply Common Reuse Principle and Common Closure Principle to define the scope of the Reuse Release Equivalency Principle, and hence define the boundaries of a sub-system (whisper it, &lt;i&gt;schema&lt;/i&gt;). Likewise we can apply the Stable Dependencies Principle and Stable Abstractions Principle to enforce the Acyclic Dependencies Principle to build stables PL/SQL libraries. So the RCCASS principles offer some most useful pointers towards a stable PL/SQL software architecture.  
&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/4360730518359520997/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/4360730518359520997' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/4360730518359520997'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/4360730518359520997'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/03/introducing-rccass-design-principles.html' title='Introducing the RCCASS design principles'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-8203435308389478354</id><published>2016-03-14T23:45:00.000-07:00</published><updated>2016-04-03T10:55:12.319-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><category scheme="http://www.blogger.com/atom/ns#" term="PL/SQL"/><category scheme="http://www.blogger.com/atom/ns#" term="principles"/><title type='text'>Introducing the SOLID design principles</title><content type='html'>PL/SQL programming standards tend to focus on layout (case of keywords, indentation, etc), naming conventions, and implementation details (such as use of cursors). &amp;nbsp;These are all important things, but they don&#39;t address questions of design. How easy is it to use the written code? &amp;nbsp;How easy is it to test? How easy will it be to maintain? Is it robust? Is it secure?&lt;br /&gt;
&lt;br /&gt;
Simply put, there are no agreed design principles for PL/SQL. So it&#39;s hard to define what makes a well-designed PL/SQL program.&lt;br /&gt;
&lt;h2&gt;
The SOLID principles&lt;/h2&gt;
It&#39;s different for object-oriented programming. OOP has more design principles and paradigms and patterns than you can shake a stick at. Perhaps the most well-known are the SOLID principles, which were first mooted by &lt;a alt=&quot;Principles of OOD&quot; href=&quot;https://www.blogger.com/butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod&quot;&gt;Robert C. Martin, AKA Uncle Bob&lt;/a&gt;, back in 1995 (although it was Michael Feathers who coined the acronym).&lt;br /&gt;
&lt;br /&gt;
Although Martin put these principles together for Object-Oriented code, they draw on a broader spectrum of programming practice. So they are transferable, or at least translatable, to the other forms of modular programming. For instance, PL/SQL.&lt;br /&gt;
&lt;h3&gt;
Single Responsibility Principle&lt;/h3&gt;
This is the foundation stone of modular programming: a program unit should do only one thing. Modules which do only one thing are easier to understand, easier to test and generally more versatile. Higher level procedures can be composed of lower level ones. Sometimes it can be hard to define what &quot;one thing&quot; means in a given context, but some of the other principles provide clarity. Martin&#39;s formulation is that there should be just one axis of change: there&#39;s just one set of requirements which, if modified or added to, would lead to a change in the package.&lt;br /&gt;
&lt;h3&gt;
Open/closed Principle&lt;/h3&gt;
The slightly obscure name conceals a straightforward proposal. It means program units are closed to modification but open to extension. If we need to add new functionality to a package, we create a new procedure rather than modifying an existing one. (Betrand Meyer, the father of Design By Contract programming, originally proposed it; in OO programming this principle is implemented through inheritance or polymorphism.) Clearly we must fix bugs in existing code. Also it doesn&#39;t rule out refactoring: we can tune the implementation providing we don&#39;t change the behaviour. This principle mainly applies to published program units, ones referenced by other programs in Production. Also the principle can be looser when the code is being used within the same project, because we can negotiate changes with our colleagues.&lt;br /&gt;
&lt;h3&gt;
Liskov Substitution Principle&lt;/h3&gt;
This is a real Computer Science-y one, good for dropping in code reviews. Named for Barbara Liskov it defines rules for behavioural sub-typing. If a procedure has a parameter defined as a base type it must be able to take an instance of any sub-type without changing the behaviour of the program. So a procedure which uses &lt;br /&gt;
&lt;pre&gt;IS OF&lt;/pre&gt;
to test the type of a passed parameter and do something different is violating Liskov Substitution. Obviously we don&#39;t make much use of Inheritance in PL/SQL programming, so this Principle is less relevant than in other programming paradigms.&lt;br /&gt;
&lt;h3&gt;
Interface Segregation Principle&lt;/h3&gt;
This principle is about designing fine-grained interfaces. It is a extension of the Single Responsibility Principle. Instead of build one huge package which contains all the functions relating to a domain build several smaller, more cohesive packages. For example Oracle&#39;s Advanced Queuing subsystem comprises five packages, to manage different aspects of AQ. Users who write to or read from queues have &lt;br /&gt;
&lt;pre&gt;DBMS_AQ&lt;/pre&gt;
; users who manage queues and subscribers have &lt;br /&gt;
&lt;pre&gt;DBMS_AQADM&lt;/pre&gt;
.&lt;br /&gt;
&lt;h3&gt;
Dependency Inversion Principle&lt;/h3&gt;
Interactions between programs should be through abstract interfaces rather than concrete ones. Abstraction means the implementation of one side of the interface can change without changing the other side. PL/SQL doesn&#39;t support Abstract objects in the way that say Java does. To a certain extent Package Specifications provide a layer of abstraction but there can only be one concrete implementation. Using Types to pass data between Procedures is an interesting idea, which we can use to decouple data providers and data consumers in a useful fashion.&lt;br /&gt;
&lt;h2&gt;
Applicability of SOLID principles in PL/SQL&lt;/h2&gt;
So it seems like we can apply SOLID practices to PL/SQL. &amp;nbsp;True, some Principles fit better than others. But we have something which we might use to distinguish good design from bad when it comes to PL/SQL interfaces.&lt;br /&gt;
&lt;br /&gt;
The SOLID principles apply mainly to individual modules. Is there something similar we can use for designing module groups? &lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/introducing-rccass-design-principles.html&quot;&gt;Why, yes there is. I&#39;m glad you asked.&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;h2&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Part of the Designing PL/SQL Programs series&lt;/a&gt;&lt;/h2&gt;
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/8203435308389478354/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/8203435308389478354' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/8203435308389478354'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/8203435308389478354'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/03/introducing-solid-design-principles.html' title='Introducing the SOLID design principles'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-951861111765160852</id><published>2016-03-01T16:11:00.002-08:00</published><updated>2016-03-16T16:57:37.465-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle. PL/SQL"/><title type='text'>Designing PL/SQL Programs</title><content type='html'>When I started out, in COBOL, structured programming was king. COBOL programs tended to be lengthy and convoluted. Plus &lt;code&gt;GOTO&lt;/code&gt; statements. We needed program desire to keep things under control.&lt;br /&gt;
&lt;br /&gt;
So I noticed the absence of design methodologies when I moved into Oracle. At first it didn&#39;t seem to be a problem. SQL was declarative and self-describing, and apparently didn&#39;t need designing. Forms was a 4GL and provided its own structure. And PL/SQL? Well that was just a glue, and the programs were so simple.&lt;br /&gt;
&lt;br /&gt;
Then one day I was debugging several hundred lines of PL/SQL somebody had written, and struggling to figure out what was going on. So I drew a flow chart of the &lt;code&gt;IF&lt;/code&gt; branches and &lt;code&gt;WHILE&lt;/code&gt; loops. Obvious really, but if the original author had done that they would have realised that the program had an &lt;code&gt;ELSE&lt;/code&gt; branch which could never be chosen; more than one hundred lines of code which would never execute.&lt;br /&gt;
&lt;h2&gt;
Let me &lt;code&gt;sleep()&lt;/code&gt;&lt;/h2&gt;
&lt;br /&gt;
Good design is hard to define: in fact, good design is often unobtrusive. It&#39;s bad design we notice, because it generates friction and hinders our progress. By way of illustration, here is a poor design choice in Oracle&#39;s PL/SQL library: DBMS_LOCK.SLEEP() .&lt;br /&gt;
&lt;br /&gt;
&lt;code&gt;SLEEP()&lt;/code&gt; is a simple program, which suspends processing for a parameterized number of seconds. This is not something we want to do often, but it is useful in testing. The problem is its home in the DBMS_LOCK package, because that package is not granted to public by default. &lt;br /&gt;
&lt;br /&gt;
DBMS_LOCK is a utility package for building our own locking mechanisms. There&#39;s not much need for this any more. Oracle&#39;s default locking model is pretty good. There is &lt;code&gt;SELECT .. FOR UPDATE&lt;code&gt; for pessimistic locking, which is even more powerful since the &lt;code&gt;SKIP LOCKED&lt;/code&gt; syntax was permitted in 11g. We have Advanced Queuing, Job Scheduling, oh my. It&#39;s hard to find a use case for user-defined locks which isn&#39;t re-inventing the wheel, and easy to see how we might end up implementing something less robust than the built-in locks. So DBAs tend not to grant execute on DBMS_LOCK without being asked, and then often not without a fight.&lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
But as developers we need access to a sleep routine. So DBAs have to grant execute on DBMS_LOCK, and then that gives away too much access. It would be better if &lt;code&gt;SLEEP()&lt;code&gt; was easily accessible in some less controversial place.&lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;br /&gt;
Why is this an example of bad design? Because user-defined locks need a sleep routine but&amp;nbsp;&amp;nbsp;&lt;code&gt;SLEEP()&lt;code&gt;has other&amp;nbsp;uses besides lock implementations. Putting&amp;nbsp;&amp;nbsp;&lt;code&gt;SLEEP()&lt;code&gt;&amp;nbsp;in DBMS_LOCK&amp;nbsp;means it&#39;s harder to use it.&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;/code&gt;&lt;br /&gt;
&lt;h2&gt;
Riding the Hobby Horse&lt;/h2&gt;
&lt;br /&gt;
Occasionally in a recruitment interview I have asked the candidate how they go would design a PL/SQL program. Mostly the question is met with bemusement. PL/SQL design is not A Thing. Yet many of us work on huge PL/SQL code-bases. How do they turn out without a design methodology? Badly:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Do you have one schema crammed with hundreds of PL/SQL program units, perhaps named with a prefix to identify sub-systems?&lt;/li&gt;
&lt;li&gt;Do you have a package called UTILS?&lt;/li&gt;
&lt;li&gt;Do you query USER_PROCEDURES or USER_DEPENDENCIES (or even USER_SOURCE) to find a piece of code which implements some piece of functionality?&lt;/li&gt;
&lt;li&gt;Do you have the same functionality implemented in several places?&lt;/li&gt;
&lt;li&gt;Does a &quot;simple change&quot; cascade into changes across multiple program units and a regression testing nightmare?&lt;/li&gt;
&lt;/ul&gt;
All these are symptoms of poor design. But there are ways to avoid this situation.
&lt;br/&gt;&lt;br /&gt;
&lt;a href=&quot;http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs-series-home.html&quot;&gt;Designing PL/SQL Programs series&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/951861111765160852/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/951861111765160852' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/951861111765160852'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/951861111765160852'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/03/designing-plsql-programs.html' title='Designing PL/SQL Programs'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-2888755919010958006</id><published>2016-01-11T20:45:00.000-08:00</published><updated>2016-01-11T20:45:56.574-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="David Bowie"/><category scheme="http://www.blogger.com/atom/ns#" term="music"/><title type='text'>Goodbye Spaceboy</title><content type='html'>&lt;blockquote&gt;
&quot;Sometimes I feel&lt;br /&gt;
The need to move on&lt;br /&gt;
So I pack a bag&lt;br /&gt;
And move on&quot;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;br /&gt;
Can&#39;t believe Bowie has taken that final train.
&lt;br /&gt;
&lt;br /&gt;
David Bowie&#39;s music has been part of my life pretty much since I started listening to pop music seriously. &lt;i&gt;Lodger&lt;/i&gt; was the first Bowie album I listened to all the way through. It&#39;s probably his most under-appreciated album. It&#39;s funny to think that back then in 1979 Bowie was dismissed as past it, a boring old fart who should be swept aside by the vital surge of post-punk bands. Because those bands were raised on Ziggy, they were taught to dance by the Thin White Duke and they learnt that moodiness from listening to &lt;i&gt;Low&lt;/i&gt; in darkened bedrooms too many times. 
&lt;br /&gt;
&lt;br /&gt;
Even if you don&#39;t listen to Bowie, probably your favourite bands did. If they style their hair or wear make up, they listened to Bowie. If they play synths they listened to Bowie. If they make dance music for awkward white boys at indie discos they listened to Bowie. If they lurk in shadows smoking cigarettes in their videos they listened to Bowie. That&#39;s a large part of his legacy. 
&lt;br /&gt;
&lt;br /&gt;
The other thing about Bowie is that his back catalogue has something for pretty much everybody. People who loved &lt;i&gt;Ziggy Stardust&lt;/i&gt; might loath the plastic soul phase. Hardly anybody gets &lt;i&gt;Hunky Dory&lt;/i&gt;; but for some fans it&#39;s their favourite album. My favourite is the first side of &lt;i&gt;&quot;Heroes&quot;&lt;/i&gt; and the second side of &lt;i&gt;Low&lt;/i&gt;, but that whole stretch from &lt;i&gt;Young Americans&lt;/i&gt; to &lt;i&gt;Lodger&lt;/i&gt; is a seam of sustained musical invention unparallelled by any other pop act. (Judicious picking of collaborators is an art in itself.) 
&lt;br /&gt;
&lt;br /&gt;
Of course, there was a long fallow period. Tin Machine weren&#39;t as bad as we thought at the time, but the drum&#39;n&#39;bass was too &#39;Dad dancing at a wedding reception&#39; for comfort.  So it was a relief when he finally started producing decent albums again.  &lt;i&gt;Heathen&lt;/i&gt; has some lovely moments.   &lt;i&gt;The Next Day&lt;/i&gt; was something of a return to form (although a bit too long to be a classic).  Then there&#39;s &lt;i&gt;Blackstar&lt;/i&gt;.  
&lt;br /&gt;
&lt;br /&gt;
It&#39;s almost as though Bowie hung on just long enough that &lt;i&gt;Blackstar&lt;/i&gt; would be reviewed as his latest album, rather than his last one.   The four and five star reviews earned through merit rather than the mawkishness which would have accompanied a posthumous release.  And it really is pretty good.  When I first heard the title track it sounded like Bowie was taking a cue from Scott Walker&#39;s latter period: edgy, experimental and deliberately designed not to be fan pleaser.  But, unlike Walker, Bowie can&#39;t do wilfully unlistenable.  Even in the midst of all that drone and skronk there are tunes.  He can&#39;t help himself, his pop sensibility is too strong.  Which is why I&#39;ve already listened to &lt;i&gt;Blackstar&lt;/i&gt; more times than I&#39;ve listened to &lt;i&gt;Bish Bosch&lt;/i&gt;.      
&lt;br /&gt;
&lt;br /&gt;
So, farewell David Bowie.  We&#39;re all going to miss you terribly.  &quot;May God&#39;s love be with you.&quot;</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/2888755919010958006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/2888755919010958006' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2888755919010958006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2888755919010958006'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2016/01/goodbye-spaceboy.html' title='Goodbye Spaceboy'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-13000143.post-2888586463308406959</id><published>2015-12-31T00:48:00.000-08:00</published><updated>2015-12-31T00:48:36.786-08:00</updated><title type='text'>Death and taxes - and Oracle 11gR2?</title><content type='html'>Oracle Premier Support for 11gR2 Database expired this time last.  However, Oracle announced they would waive the fees for Extended Support for 2015. This was supposed to provide 11gR2 customers an additional twelve months to migrate to 12c.  So, twelve months on, how many of those laggards are still on 11gR2.  My entirely unscientific guess is, most of them.  Why else would Oracle announce the extension of &lt;a href=&quot;https://blogs.oracle.com/UPGRADE/entry/no_extra_fee_for_extended&quot; alt=&quot;Mike Dietrich&#39;s blog&quot;&gt;the Extended Support fees waiver until May 2017&lt;/a&gt;?  
&lt;p&gt;
But 11gR2&#39;s continued longevity should not be a surprise.
&lt;p&gt;
For a start, it is a really good product.  It is fully-featured and extremely robust.  It offers pretty much everything an organization might want from a database.  Basically it&#39;s the Windows XP of RDBMS.
&lt;p&gt;
The marketing of 12c has compounded this.  It has focused on the &quot;big ticket&quot; features of 12c: Cloud, Multi-tenancy and In-Memory Database.  Which is fair enough, except that &lt;a href=&quot;http://docs.oracle.com/database/121/DBLIC/options.htm#DBLIC140&quot; alt=&quot;Oracle 12c Licensing Guide&quot;&gt;these are all chargeable extras&lt;/a&gt;.  So to get any actual benefits from upgrading to 12c requires laying out additional license fees, which is not a popular message these days.
&lt;p&gt;
And then there&#39;s Big Data.  The hype has swept up lots of organizations who are now convinced they should be replacing their databases with Hadoop.  They have heard the siren singing of free software and vendor-independence.   In reality, most enterprises&#39; core business rests on structured data for which they need an RDBMS, and their use cases for Big Data are marginal.  But right now, it seems easier to make a business case for the shiny new toys than spending more on the existing estate.
&lt;p&gt;
So how can Oracle shift organizations onto 12c?  They need to offer compelling positive reasons, not just the fear of loss of Support.  My suggestion would be to make a couple of the Options part of the core product. For instance, freeing Partitioning and In-Memory Database would make Oracle 12c database a much more interesting proposition for many organizations.  
 
</content><link rel='replies' type='application/atom+xml' href='http://radiofreetooting.blogspot.com/feeds/2888586463308406959/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/13000143/2888586463308406959' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2888586463308406959'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/13000143/posts/default/2888586463308406959'/><link rel='alternate' type='text/html' href='http://radiofreetooting.blogspot.com/2015/12/death-and-taxes-and-oracle-11gr2.html' title='Death and taxes - and Oracle 11gR2?'/><author><name>APC</name><uri>http://www.blogger.com/profile/18348719053445885097</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='23' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj_k1Ah3zyuoViG5u_T0p9hTPY6P5i0RYCqgyEHHnrvg1bsnytEl4KTWgHyeRmtaDOTajPAVRUGsa2uCL8xvcCphBlqTmXEY2GOEoifTZPJo3p_4PfxD-PAF6H2IaJBKSs/s1600/apc.jpg'/></author><thr:total>1</thr:total></entry></feed>