Showing posts with label software development. Show all posts
Showing posts with label software development. Show all posts

Wednesday, November 9, 2016

DevOps as an Aspiration

Yesterday I gave a tech talk to my colleagues about how we are using Bitbucket and Jenkins for continuous integration. The talk focused on the things way Bitbucket could be used to integrate with Jira, and how we've set up Jenkins to build and deploy the various branches. It had the title "Towards DevOps".

Towards is the right word to describe what we are doing. The ideal of Dev to Production in 60 minutes is unachievable for many reasons, but the kinds of things that enable such operations are still useful.

So for us, we wanted to use the setup to improve quality control. Successful compilation and running of unit tests is a necessary step before releasing code, and linking Bitbucket to Jenkins gives us that seamlessly.

We also wanted to automate deployments, so that we can go into the Test environment at any time. We could use Jenkins for this and have the operation launched with the click of a button (actually 2 clicks because we have a customisable deployment script for choosing branch, build, and environment.)

This setup is limited to the lower environments and is far from complete. For one, DB scripts are completely manual and reliant on one person. But we are looking to fix that, just as we are looking to include Change Management for automated deployments into the higher environments.

Whatever we end up with will not overturn the enterprise setup. But it has already put us in a better position than we were before, and given us a target on how to further improve things. The corporate culture is not an excuse for making things better.

Thursday, November 3, 2016

There will Always be Resistance to Change

The complaint I have heard the most often any time myself or others in my team have pushed forward with a new idea is "but that's not the way we do things". The appeal, when divorced from the obvious truth of such a statement, is that what we currently do works. So what advantage would we get from changing?

This is a question we always need to ask ourselves, because being agile is not change for the sake of change. There is usually an identification of a deficiency, inefficiency, or bottleneck that the suggestion tries to address.

We have a deficiency now in that the database changes are wholly separate to the code changes they align with. When we deploy, we have to coordinate with the DBAs to make sure they run their scripts at the right time. This is fine when they are available, but a problem when they aren't.

But even if they were always available, it's a coordination problem that can be easily solved by scripting. As it stands, anyone can deploy to Test whenever there is a need to do so. And there's currently no obvious way beyond the developers knowing what changes are going in as to whether the DBA is required.

Evidently this is a fairly common problem because there are multiple products that solve it by introducing DB versioning. The main resistance is getting the DBAs themselves on board.

They are correct in that it's a cultural change, moving away from a system that works. But it's a necessary change because the system as it works has obvious (and sometimes painfully pressing) limitations. We want this change because we can and need to do better than what we have.

It's good to have a reminder that development is largely people, so we should be mindful of how people can react to being asked to change.

Friday, October 28, 2016

Burnout

I describe the agile process as sustainable development. The idea is that development should be able to be continued indefinitely. This is a big change from the usual development approach of big pushes and lulls.

It's a old habit, and old habits die hard. We know we can push harder at times to get over a line. And as individuals, we suffer for doing that. We run the risk of burnout.

We recently jumped deep into a problem that was complex and time sensitive. It required a big effort to get it over the line. At the end of it we made it, but it came at a cost. The following sprint has been deflated, with tired developers, a lack of enthusiasm and focus, and inevitably more mistakes.

The scrum process is set up to avoid this. That we agree to take in what we can handle, and base what we take in future sprints from past performance. We learn what we can achieve from what we have achieved. So those moments we go above and beyond throws that out.

It's an achievement to deliver 4 weeks of work in 2. But if the cost is tired unmotivated developers, there had better have been a very good reason for doing so.

Wednesday, October 26, 2016

Whatever Tools for the Job

When I was a child, I was amazed at just how many tools were in my grandfather's workshop. I didn't even know what most of the tools did, let one why there would be so many.

My toolkit is virtual rather than physical. Like the craftsman, knowing which tool is right for the job and how to use it effectively is vital.

One recent task I had to do was to query our database and get some intelligible information from it. To do this, I used a combination of SQL Developer and Excel, taking advantage of features in both to perform the task. A DBA may have been able to solve it purely in SQL (just as I'd easily be able to solve it with a targeted Java function), but the combination of tools worked for me. I used SQL Developer and Excel for what each was good at doing.

Knowing multiple ways to solve a problem gives flexibility when issues arise. Sometimes a spreadsheet or even Notepad are the right tools for the job in the right circumstances.

Wednesday, October 12, 2016

Purposes of Unit Testing

  1. As a development process
    Test-driven development is a useful skill to learn. It encourages a clean design, as writing unit tests for messy design is both painful to write and painful to maintain. It also gives a target to code against, by setting what what the function ought to achieve before the function is even written.

  2. Proving the code behaves correctly
    Writing unit tests is the simplest way to show that code does what it is meant to do. Unit tests allow easy checking of boundary conditions, to ensure that the function behaves as expected.

  3. Demonstrating robustness
    In complex systems, well-written unit tests demonstrate that functions behave as expected. As more features are added, or as code is reused, unit tests demonstrate that these changes do not affect the existing functionality. Conversely, if unit tests easily brake when code changes, it's a good indicator of fragility.

  4. Testing
    Some tests algorithms are better for than humans. When testing a function involves a large amount of data, unit tests are best equipped for this job. This is also true for time-dependent functions, or testing algorithms.

  5. Refactoring
    Unit tests provide the assurance needed that refactoring the codebase hasn't accidentally changed functionality. Without unit tests, refactoring is fraught with risk.

Tuesday, October 11, 2016

Chickens and Pigs

A Pig and a Chicken are walking down the road.
The Chicken says: "Hey Pig, I was thinking we should open a restaurant!"
Pig replies: "Hm, maybe, what would we call it?"
The Chicken responds: "How about 'ham-n-eggs'?"
The Pig thinks for a moment and says: "No thanks. I'd be committed, but you'd only be involved."
Most people who are involved in a project are not committed. They are chickens. And while they make decisions that affect the project, they are not committed in the same way as the development team are.

The development team are the ones who are responsible for what is delivered. They are pigs. Their actions directly affect the project.

A chicken making decisions on behalf of the pigs can adversely affect the team's ability to do their job. As the chicken has no skin in the game, their decisions are divorced from the consequences.

A pig who acts like a chicken is also problematic. If they are not committed to delivery, their involvement detracts from the team's collective ability to deliver.

Wednesday, October 5, 2016

Book Recommendation: The Nature of Software Development

Development has more than enough to keep anyone occupied on immediate concerns. But it's worth standing back in order to reflect on what it is we are doing.

The Nature of Software Development by Ron Jeffries can best be seen as an expansion on the agile manifesto. Like the manifesto, it's high level but gets right to the point. Like the manifesto, it's concise but profound. And like the manifesto, the aim is to identify what makes for successlooks like.

What we are doing when building software is trying to add value. The word can mean different things in different contexts, but in this case it is a strength rather than a weakness.

We build software because the software will serve a purpose. We should focus on delivering that which serves that purpose, and not waste time on features that are superfluous to that.

We should develop such that there will be value if the project winds up tomorrow. The code should always be ready to deploy. We should fix problems as we go along because that makes development quicker in the long run.

There's much more to the book than I'll cover here. It's a short book, and conversational in tone, and that fits with the message the cook conveys. Deliver what adds value, and don't waste time with filler that doesn't. This book is very valuable.

Tuesday, October 4, 2016

90% of Development is People

When I started out in software development, my biggest concern was my lack of technical ability. Each annual review I flagged technical proficiency as an area of improvement.

After about 5 years and a few projects, I was put on an assignment with absurd deadlines on a different technology stack. This forced me to talk to people more about what I was doing. This was a gestalt moment for me, as it forced me to see software development in a new light.

Raw technical proficiency has its place, and some jobs require it - 3D engine programmers, for example. But for the enterprise work I do, soft skills matter.

The ability to negotiate matters because ideas are seldom unambiguous. It also matters in navigating what can be achieved in the face of unrealistic expectations.

The ability to foster trust matters because it's essential for team cohesion and fostering working relations.

Being able to effectively communicate matters because if we can't express ourselves to others, then we can't get our ideas across.

Being able to listen matters because others need to be able to get their ideas across to us.

And being able to put all that together matters because effective collaboration requires all those skills. A developer who can collaborate is in a far better position than one where those skills are lacking.

Monday, October 3, 2016

Shuhari: first learn, then detach, and finally transcend

From Wikipedia:
  • shu (守) "protect", "obey" — traditional wisdom — learning fundamentals, techniques, heuristics, proverbs
  • ha (破) "detach", "digress" — breaking with tradition — detachment from the illusions of self
  • ri (離) "leave", "separate" — transcendence — there are no techniques or proverbs, all moves are natural, becoming one with spirit alone without clinging to forms; transcending the physical
When we learn something new, the accumulated wisdom of those who came before is the best place to start. We follow what they say because they know what they are talking about. This is shu.

As we progress, we are able to identify where the rules work for us and where they don't. We are in a position to know the difference between what works and what doesn't, so breaking the rules gives us valuable feedback. This is ha.

Finally we are in a position where the rules no longer matter. We have developed through experience practices that serve us well, as well as learnt many bad practices to avoid. This is ri.

Monday, September 26, 2016

Following the Boy Scout Rule

"Always leave the campground cleaner than you found it."

In all my years as a software developer, the only times I've ever gotten to start from scratch is when I've worked on personal projects. And even then, starting from scratch is a last resort.

My experience of being a programmer is working in someone else's architecture. I get to expand it out, fix it up, and sometimes refactor it away. And each time I end up having the same question - why is it built that way? And each time there's the same answer - it's because the code needed to be delivered quickly.

It feels at times that all we can do as programmers is try not to make things worse. One thing I've done is tried to fit in with the existing way of doing things. That way the code is consistent for those who maintain it in the future. But it doesn't solve the problem, merely prevents it from getting any worse.

The answer is meant to be refactoring, though it's really not an answer for fragile code. It's a sad irony that the code in most need of refactoring is the code least able to be refactored...

Any complex system is going to seem impenetrable at first glance, but there are ways to improve it. A system doesn't need to be overhauled to be fixed, and something as simple as tidying up the code that's being worked on is enough to make things better.

For this project, we have pretty abysmal unit testing. So one rule we've set for ourselves is to put unit tests in wherever we find ourselves enhancing the code. Coverage is still woeful, but it is less woeful than it was a month ago. Another thing is to make sure no commit has commented-out code.

Code doesn't get to a messy state by a single act, nor can it be fixed in one. The complex mess that is the average codebase (at least average from my experience) is the way it is because of a long path to that state. Making things better is a similarly long path, but thankfully one that be addressed as part of enhancing a system. Fragility is quantitative, not qualitative.

Monday, September 19, 2016

From Feature Branch to Gitflow

When we migrated from SVN, one of the first acts was to lock down the master branch. This was mainly to get developers used to the Git way of doing things, so hopefully to reap the benefits that comes with proper usage of branches.

The ideal, however, has been to get to a Gitflow model. The idea is to have easy access to the Production code - should the need arise - and that fits well with the Git branching model. This could have been retrofitted to our migrated codebase, but we didn't do it as we thought the best thing to do was get the team used to Git first.

Here's the path we took to incorporate Gitflow:
  1. Create a release branch - This branch incorporated all potential fixes found in the preprod environment while preparing for production. This branch could only be changed by pull request, so the developers would branch off it if needed. A job in Jenkins was set up to build the release branch.
  2. Do the release - The latest artefact built from the release branch was promoted to production.
  3. Create a production branch - A new branch called production was set up in Bitbucket. On the branching model tab, this branch was set as the production branch. The current release branch was merged into it.
  4. Finalise the release - At this point, we put an exception on the restrictions to the release branch: the release manager. The release manager removed the SNAPSHOT from the version number and committed, so Jenkins would build the final version*. The release version was then incremented to the new SNAPSHOT version.
  5. Merge back to master - All the release changes were merged back into the master branch. As the branch had served its purpose, it was deleted.

*I really don't know why we do this after production rather than immediately before the production deployment. It seems odd to deploy SNAPSHOT code into production.

Friday, September 16, 2016

Embracing Shadow IT

Back in 2009, I was put on a project with a very short time frame and a lot of work to deliver. A couple of the senior developers looked at the resources and technologies at our disposal, and they realised they were inadequate for the task at hand. So we set up a completely open source solution - developed on Eclipse instead of RAD, tested on Tomcat instead of WebSphere, used SVN instead of ClearCase, and hooked into Hudson.

All this was running on a spare machine sitting on my desk. And of course, we had to keep it a secret. It all came to a head two project managers later, but it is a vindication that when I returned to the department years later, many of those tools had become the norm.

There is a term for this: Shadow IT. And it comes about because no enterprise-wide solution is going to cover everything that needs to be done. In 2009, the computers we had weren't powerful enough to effectively develop on RAD or WebSphere. ClearCase didn't give us continuous integration, and is a generally burdensome source repository compared with SVN.

(In late 2010, I switched projects in the department to one that used the official set of tools. The team had just lost 7 days to a ClearCase outage, despite it having paid support. We never lost any time running SVN.)

What surprised me about our switch to the Atlassian suite of tools is we are still in a semi-secretive state about it. It's a tool for our section, that we are meant to deny knowledge of to outsiders. The tools and their relative effectiveness are of interest to others, and better practices only come by demonstrated utility. Otherwise we're beholden to sales pitches to people who aren't directly affected by the the products being bought.

The whole point of going agile is that teams individually can reflect on what works (and what doesn't!), so they can respond for the future. Having severe constraints on their tools limits their capacity for change, thus making the exercise less effective.



For us, we are certainly benefiting from using our own tools. JIRA is far better for collaboration than the physical boards we had. Confluence is more intuitive and powerful than Sharepoint. Bitbucket has many advantages over SVN. But most of all, we've got a development team excited and engaged with the tools - a far better situation than the usual stream of complaints that have been ubiquitous in every workplace I've been in.

Wednesday, September 7, 2016

Going Agile: The Elevator Pitch

What we are trying to achieve is to change the way IT interfaces with business. Instead of business trying to work out ahead of time all the details they want, the business collaborates with IT to work out what the requirements are.

This is further broken down into time, with development continuously delivering functionality. The business doesn't need to have every detail set out ahead of time, but just enough of an understanding of the features that development can take place.

The advantage of this is that development becomes a feedback loop, where features can be gradually introduced, changed, enhanced and even removed based on business requirements. In short, it allows business to concentrate on what is needed, and for IT to respond to these needs as they arise.

Tuesday, September 6, 2016

How to Git: Branch, Code, Merge, Delete, Repeat

Switching technologies under people is a great way to learn about implicit understandings people have about how to use the technology. With the branching model in Git, it brought out just how people see their own development as a solo enterprise.

The common reaction was to think that each person has their own branch to work with, rather than a branch serving as a unit of work. This highlights one barrier to better collaboration, but also can limit the effectiveness that branching in Git provides.

The best way I've found to deal with branching in Git is as follows:
  1. Branch - When starting a new feature, branch from the head of the development branch. This ensures you are working with the latest deployable code.
  2. Code - Your regular development work. Commit as needed as it backs up your work, as well as allowing for collaboration.
  3. Merge - When your coding is done, merge it back into the development branch.
  4. Delete - After you merge the branch back to the development branch, delete it. Leaving it just creates clutter, and clutter that goes quickly out of date at that.
  5. (if needed) Repeat - If it turns out steps 1-4 didn't cover the feature, start the process again. Don't worry about maintaining a branch for the possibility that feature still needs to be worked on.

The ideal is that branches are short-lived. The longer a branch lives, the more likely there are to be merge conflicts when it's brought back.

With JIRA and Bitbucket, it's easy to create a branch named for a particular feature. So anyone seeing a branch will at a glance know what unit of work that branch is for. And since this can be done multiple times, having to recreate a branch when more aspects of a user story emerge is simple.

Monday, September 5, 2016

The Beauty and Necessity of The Agile Manifesto

Of all the documentation I've read on agile, the one thing I keep referring to in conversation is the Agile Manifesto. For reference, here it is:
We are uncovering better ways of developing software by doing it and helping others do it. Through this work we have come to value:

Individuals and interactions over processes and tools
Working software over comprehensive documentation
Customer collaboration over contract negotiation
Responding to change over following a plan

That is, while there is value in the items on the right, we value the items on the left more.

Whenever I'm pulled into meetings to discuss the agile process, I think of this manifesto. Whenever someone asks me about how we are collaborating with business, I think of this manifesto. Whenever the very question of agile comes up, I think of this manifesto.

I even have the manifesto printed out and stuck to my desk!

The beauty of the manifesto is how much it says in so few words. The terms are broad enough such that they don't get bogged down in any particular aspect of the SDLC. Yet the terms are also targeted enough that they hit the relevant factors associated with software development.

Furthermore, they are a statement of intent - of what a software developer ought to strive for. The goal is working software, and to get that requires interaction, collaboration, and responding to change.

Those things on the right too often get in the way of creating working software. We've all been in projects where managers put pressure on the team because it deviates off their unrealistic "plan". That bad ideas get coded in because the phase to negotiate that was before coding began. That a effort is put into elaborate documentation that goes out of date the moment a system enhances it.

Even when going agile, the agile manifesto works to dampen the tendency to think any problem can be solved with more process. It can stop those in-grained waterfall tendencies from answering the inevitable "now what?" question.

Thursday, September 1, 2016

From Java Dev to Scrum Master

My previous workplace did classic Waterfall, which meant coming on and going to spec review meetings while waiting for the final green light to start coding. And I came on just before development was due to ramp up - in this case, about 6 weeks.

That was 6 weeks of reading elaborately crafted specs set out in a systematic way, and occasionally going to long tedious meetings where minor details were argued over. All this for what turned out to be a few weeks of actual development, before the long wait for testing to be complete and into production.

By the time I left, we were a few months into the design phase for the next project, with coding due to start just as soon as the specs were signed off.

The place I entered had just started taking on an Agile scrum methodology in software development. In the space of a month, I had gone to arguing over the minutiae of 100 page specifications to being asked to size stories based off a two line description and 5 minutes of discussion among the team. It was quite the culture shock!

It took a few sprints, but we slowly established a good team working ethic. When I came on, there was pessimism about whether the agile process could deliver anything other than more process for us to follow. But over the next 6 sprints, we made it work and got a high quality product out on time and with a good working relationship between business and IT.

So that brings me to where I am now. I've come out the other side of a scrum agile project as a scrum master for another. That means taking on a lot more of the organisational side of things, and consequently having a lot less time doing actual development. And it's meant spending time working out how to integrate the tools we have seamlessly into our workflow.

The way I see this blog is this - it's a way to collect my thoughts on the agile process as a whole. To write out some of the things I'm learning as I'm learning them, and to reflect on the practical realities of agile software development as I see it. I've been happy to wear the developer hat for close to a decade now, so will be an interesting journey for me to be immersed in a different aspect of the process.