This is a good glimpse into my thought process regarding helping companies and teams doing software projects.
Agile in the Context of a Holistic Approach
This is a good glimpse into my thought process regarding helping companies and teams doing software projects.
Well, this is sort of what I like to do on software development projects…
I feel like there are some necessary startup processes to get you up and running quickly with a glimpse or vision of the product/end goal. And then some set of similar, or refined, or slightly modified practices that carry on during the life of the main product development period. I liken it to getting the skeleton up and running, or the “tree trunk and main branches” upon which we can rapidly build out the app.
This was part of a “Day of Agile” immersion course where the attendees step through a mock development project…
PDF: Iterative Development Path Agenda.
PNG: Iterative Development Path
Well, in a nutshelll, agile is a state of mind.
Agile is relative.
Agile is not dogmatic.
Agile is pragmatic.
Agile is designed to reduce the gap in time between doing something, and seeing a result that you can “measure.”
Blend in Lean concepts.
Read The Goal.
Don’t do giant monolithic things.
Learn how to decompose your “features/expected outcomes” into bite-size chunks.
Don’t plan across a far horizon to the same degree.
What folks are tasked with doing today better be clear and have unambiguous meaning of “DONE”
What folks are tasked with doing in 2 months better be rather nebulous and broad.
Don’t be complacent and relax.
Question the value of deliverables that are needed to fulfill some process step for some other team.
Ask any downstream recipient what they truly need — and why.
Try new processes.
Reflect.
Agile takes constant effort and constant partial attention if you are doing it right.
Be holistic.
Innocently enough, one of our developers added this feature, which passes:
Scenario: Create Field When I manage the "acme" org And I go to the user field management list for "acme" And I click "New" And I set the following values | Name | Test Field | | Required | true | And I click the "Create" button Then I should see "Test Field" And I should see "test_field" And I should see "Yes"
Note: for now I am not going to discuss the other improvements that could be done with this feature (e.g., to remove the “click” steps).
Unfortunately, the actual page looked as follows (using save and open page):
Name Required? Key First name Yes first_name Last name Yes last_name Test Field No test_field
Sure enough, the text “Yes” was indeed on the page, given the step was defined simply as shown below. However, the intent of the test was actually not correctly followed in the code.
Then(/^I should see "(.*?)"$/) do |text| expect(page).to have_text(text) end
So one way to ensure the proper data appears in the proper place on the page, especially when it is in a table, is to do the following.
Add an ID to the page location:
%table %thead %tr %th.text-center Name %th.text-center Required? %th.text-center Key %th.text-center %tbody - user_fields.each do |field| %tr{id: dom_id(field)} %td.text-center= field.name %td.text-center -if field.required Yes -else No %td.text-center= field.key
Change the feature to expect the text exists in the context of the record:
Scenario: Create New Field Given I follow "User Fields" in the sidebar And I follow "New Field" And I set the following values | Name | Zodiac Sign | | Required | true | And I click the "Create" button And I should see the following user field: | name | required | key | | Zodiac Sign | Yes | zodiac_sign |
And define a step something like this:
Then(/^I should see the following user field:$/) do |table| # table is a table.hashes.keys # => [:name, :required, :key] field = UserField.find_by(name: field_name) dom_id = "user_field_#{field._id}" table.hashes.each do |row| dom_id = dom_id_for_field(row[:name]) within("tr##{dom_id}") do expect(page).to have_text(row[:key]) expect(page).to have_text(row[:required]) end end end
I also like to check my tests! That is, go to the code where the text “Yes” is defined, and change it to something else. If your tests still pass, you know your test is flawed!
By adding a “findable” id to the output, you can more exclusively assert some text is on the page in the correct location!
FDD?
I bet you never heard of Feature-Driven Development, eh?
Well, Mike Cohn wrote this recent post:
Love the Zurb Foundation stuff. Love that they freely open-source these cool tools and provide documentation to the community. So, it is hard to complain about “free.” But, in the spirit of community, I think our frustration is often due to being excited about trying out a new, cool, thing, and getting bummed out when running into small roadblocks. (Especially for me, a hacker, who is not really qualified to jump in and discover some crazy cascading javascript or CSS explanation for the odd behavior.)
The disjointed and terse example on the Magellan docs page does leave one asking for more details.
Disjointed example:
Arrival
Destination
I had a great deal of trouble to get the nesting correct on my page that also included the topbar element. There seemed to be conflicts with having the topbar being contain-to-grid
and fixed.
From what I have gleaned by looking at the page source and doing a lot of trial and error (), I got something to work “good enough” (as I got tired of the trial and error):
An example in haml (sorry for not doing it in HTML, but this is ripped from an app I am writing — modified slightly for this post):
- structure_elements = %w(Access Interior Roof Shutoff Drain FloorPlan SiteDetails) - structure = @structure %div{"data-magellan-expedition" => "fixed"} %dl.sub-nav - structure_elements.each do |element| %dd{"data-magellan-arrival" => element} = link_to element, "##{element}" %article#structure %h4 = link_to structure.name, edit_structure_path(structure) = link_to fa_icon('pencil'), edit_structure_path(structure) %hr = render partial: 'photos/photos', locals: {context: structure, preplan: preplan} - structure_elements.each do |element| %a{name: element} %h3{"data-magellan-destination" => element} = element %div.panel ="#{Faker::Lorem.paragraphs(3).join(' ')}"
I hope this helps
I am using Kaminari paging gem and Zurb Foundation 5, and here is what I did to make them work together in HAML fashion:
If you generate the theme (it might not matter which one), for example:
rails g kaminari:views bootstrap
You can see all of the “machinery” in the viewskaminari
folder. Here is my “hack” to get Foundations Pagination working with Kaminari:
I tweaked _paginator.html.haml
to reflect the Foundation class on the %ul
tag:
= paginator.render do %ul.pagination ...
And I tweaked _page.html.haml
to reflect Foundations current
class (instead of Kaminari’s active
class):
%li{class: "#{'current' if page.current?}"}
And then it just worked!
One of my quips that people seem to get a kick out of is:
“A fool with a tool is still a fool”
My point is simple: woodworking tools in the hands of craftsmen can produce fine furniture or musical instruments. But merely the availability of great tools “doth not a masterpiece make.” Not to take the woodworking analogy too far, but power tools can also make it easier for the amateur to get hurt.
The reason a quality piece can be turned out more efficiently with a tool is the ability for the craftsmen to more quickly realize the design and architecture. In addition, tools can help make patterns easier to replicate. From actual patterns (like certain cross-section shapes on molding), to templates (like violin bodies), to connectors (like Kreg pocket hole jigs). A woodworking shop will also make good use of building components to put into larger assemblies.
So, tools in the hands of experts can help realize the design. Tools that are able to help apprentices produce parts designed by the masters, can help produce more output and help train the apprentices.
But put me in a room with the most awesome woodworking tools, and I will not be producing Stradivarius-esque violins any time soon (or ever, most likely).
As I read this account of transitioning from Java EE to Ruby on Rails,”Java Web Apps to Rails, A Developer’s Experience,” I thought the following:
Regarding the lack of a good Ruby/Rails IDE:
When it was time to look at the code, I was a bit disappointed. TextMate looked like a popular choice but it fell short in many ways. I struggled to navigate the code, link the methods across files and follow the code. Grep was my only savior.
I am surprised he did not find RubyMine. JetBrains makes awesome IDEs (IntelliJ IDEA for Java, too). I have to admit at being very impressed that the underlying model of the ruby code within the RubyMine IDE is amazingly capable of giving you the same sort of features that it can for a “compiled,” or more type-centric language like Java.
Next he mentioned about learning the language…
My approach to learning Ruby was to start looking at code and figuring out pieces of syntax that did not make sense. That turned out to be a bad idea. Constructs like “do |x| x+1” threw me off. … I found it very important to understand the motivation behind creating the new language.
There are some good books out there, and other resources…
Another comment rang true with me:
I found it very important to understand the motivation behind creating the new language.
More about the motivation behind Ruby… or at least, how I interpret things.
Ruby treats you like an adult. It doesn’t baby you, or hold your hand, or make you type all sorts of (obfuscating, in my opinion) fluff that a compiled language needs. Your code is more compact and obvious and “dense with meaning,” leading to less need for things like method return types and method parameter data types. Or semicolons.
However, I miss parameters list, curly braces, return statements, camel case naming conventions…
Be patient… soon you will grow weary of having to read all that extra stuff when you go back to Java. If you write well-formed classes, and very small, compact, and obvious methods, you don’t need the extra frills. You will run across the concept of “duck typing” which really means that classic C++/Java/C# style interfaces are not needed. If you create a method that expects a passed-in object to respond to a method call (e.g., “torque”), any object of any class will do — as long as it has that method call! And if you pass in an object that does not have that method, Rails will kindly throw an exception.
The concept of ‘open classes’ that allow developers to go in and change a base class sounds scary.
Go back to my opening statement. “Ruby treats you like an adult.” If you are naive, you can blow your code up and break stuff. If you do everything the Ruby way, you’ll be fine — because you will catch it with tests (right?). There are good rules of thumb for how and why and when you should consider adding to an existing class — or worse, monkey-patching. In Ruby you can actually alter the behavior of an existing method of an existing class. Do it poorly, and you will pay the price. And maybe not for a year or two. Mwahahahaha.
Ruby’s metaprogramming is incredibly powerful (even if the syntax takes a bit of getting used to).
Rails is incredibly opinionated about how the MVC code should look. It is basically a model-driven architecture approach. The framework expects the MVC stack to have a model, a view, and a controller for each domain concept. (As a long-time domain modeler, and UML guy, this is a real treat.) You can use the default rails generators (interesting when first starting, or for banging out a quick prototype), or write your own twist on a generator. Instead of focusing on the boring framework bits with repetitive, template-like code for each domain object, you can focus on quickly creating features that people want to use and pay for 🙂
Ruby on Rails has a great ecosystem of wonderfully talented folks providing 1000s of gems to do all sorts of useful things. For example:
The ecosystem of supporting tools is incredible. Some of my favorites:
These all make it so easy to “do the right thing” and write code with BDD/TDD to provide quality from the start.
Personally, my switch from J2EE to Rails (not to mention SQL to NoSQL/MongoDB) has been one of pure pleasure. The kinds of rich functionality and the ability to build stuff faster is imprerssive. I only wish I were better at writing kick-ass Ruby, Rails, CSS, Javascript, MongoDB…
Is it perfect? Of course not. There are other cool things to look at as well… Meteor, Node.js, MEAN, etc. So much to explore, so little time.
Back to my continuous learning!