• Skip to content

Custom Software Development | Cypress Mill Co.

(256) 580-6680

  • Home
  • About Us
  • Contact Us
  • Services
  • Blog

Development

August 10, 2020 By Nick Andrews

Why the Development Process Matters

When a client comes to us with a request for a new feature, a change to an existing one, or a full-fledged project, our development process provides a strong foundation for our team to meet those needs.

Taking into account budget and desired time of completion, we assess the programming requirements to sufficiently test and develop software that is reliable and easily maintained. Our development processes allow us to build on top of our previous work at an accelerated pace, and in turn provides our client confidence that any future work will be completed in a timely and budget friendly manner.

The testing and development stage of our process is designed to provide our team of developers with a foundation in which to quickly and confidently develop software that meets or exceeds the needs of the project.

A combination of unit, integration, end to end, and user interface tests are created and used to bring assurance the code we write works as expected for current and future projects. Testing allows our developers to focus on their assigned task without worry that they might break something in another part of the application. Another key aspect of testing is that we are often able to find and fix potential issues before they occur in the real world. Most importantly, our testing methods ensure our clients can trust in the software applications they present to their users.

In software development, it is important for code to be written in a manner that is efficient, readable, and maintainable.

Code efficiency is not solely based on how fast a piece of code runs. Efficient code is often clear in its logic and written with a touch of simplicity. Writing code with concise and simplistic intention allows the code to be easily read and understood by other developers, which is often referred to as readability. Maintaining readability ensures the intention of the function or method written by the code author is easily and accurately interpreted by other developers who may need to interface with or refactor the existing code.Refactor is a term often used to describe the act of improving upon an existing piece of software. There are times when developers may need to refactor a piece of code to allow it to be more reusable in other parts of the application or just to simply optimize an existing method or function for better performance. As the code base grows over time, it is crucial for developers to write and refactor code in such a way to allow it to be easily understood and maintained by anyone who works within the code base. Keeping a focus on efficiency, readability, and maintainability allows our team to deliver requested features for our clients in a timely fashion.

Another key component of our process is peer code review. Code review is a great way for development teams to provide feedback that not only helps improve the team’s skills, but it also prevents mistakes that could be costly to the client. Before newly written code is included in the production code base, we have another member of the development team review our code for any errors or potential issues. This practice is another step in our process that often helps to prevent issues before they could ever happen in production. Aside from catching bugs, the code review process also creates an avenue in which the reviewer could suggest an alternative approach that could potentially lead to less development time needed for future feature requests.

Along with code review, each new piece of code must also pass our continuous integration tests before being included in the production code base. Continuous Integration is a development practice in which developers integrate code into a shared repository frequently. Automated tests are run to ensure the newly written code can be integrated into the code base without conflicts or errors. This is a critical aspect our process that allows our team to quickly develop new software together without worry of conflicting with something that another developer has written.

Last but certainly not least, support and maintenance on the code base allows our team to ensure products work for the clients as expected now and into the future. Future software changes may be necessary for many reasons. Whether it is updating a section of code that no longer works correctly due to a web browser update, or a client’s customer has a question about the application, we strive to provide service and support that goes above and beyond. Each step of the process is equally important in the growth of our development team’s success as well as the success of our clients we are fortunate to work with. By sticking to the design of our development process, our team is able to develop and maintain software quickly and efficiently while building long lasting relationships with our clients.

Filed Under: Development

May 28, 2020 By Jacob Senecal

To Blog or Not To Blog…

Since I started Cypress Mill Co almost two and half years ago, I’ve been hesitant to start a blog for our company, thinking that it might be too much work to develop new content and wondering if we really have anything of value to offer readers. I’ve finally come around to the idea, and I’d like to tell you why. 

It’s easy in the daily grind of working on new features and resolving issues for our customers to lose sight of who we are and what we have to offer. We are a team of hard-working professionals, doing our jobs remotely from locations throughout the Southeast US. Sure, there are lots of other developers and teams out there just as qualified and proficient as us, and impostor syndrome can sometimes make us wonder just how qualified we really are. But the truth is, we know our craft, and we’re constantly getting better. I know this is true because time after time I see our team members rise to new challenges. Complex features are built and technical problems solved, and most importantly customers are not just satisfied, but impressed.

When I see the professionalism of our team, their incredible work ethic, and the way they support each other and work as a team, I realize that we have something that is actually pretty unique and special. And in that realization I also recognize that this team deserves a platform to share the knowledge and insight they have worked so hard to achieve for themselves, and that our customers and peers deserve to see just how amazing these people are!

I’m looking forward to seeing the posts that will appear here in the coming months and years, because I have a feeling that they will be interesting and informative, and they will give folks a little glimpse of the quality individuals that I feel privileged to share this company with.

Filed Under: Development

May 21, 2020 By Edward Monson

Exploring Django Models with _meta

When you’re testing or debugging a Django application, it’s often helpful to get a list of a model instance’s fields and their values. Let’s say you’re debugging a view involving some models like these:

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

and you want to quickly see their fields and values at a breakpoint. Django models have a _meta api that allows you to retrieve a model’s fields, among other things.

 

Let’s see what the question looks like at this breakpoint:

def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    import pdb; pdb.set_trace()
    return render(request, 'polls/detail.html', {'question': question})
 

question is an instance of the Question model. _meta is a field of a Model, not its instances, so we need to get question‘s Model:

(Pdb) question_model = type(question)
 

Now we can get question‘s fields:

(Pdb) question_model._meta.get_fields()
(<ManyToOneRel: polls.choice>, <django.db.models.fields.AutoField: id>,
<django.db.models.fields.CharField: question_text>,
<django.db.models.fields.DateTimeField: pub_date>)

That’s not the most helpful output, but we can get the names of the fields like this:

(Pdb) question_fields = question_model._meta.get_fields()
(Pdb) [f.name for f in question_fields]
['choice', 'id', 'question_text', 'pub_date']
 

With these field names, we can get question‘s values:

(Pdb) field_names = [f.name for f in question_fields]
(Pdb) print(list(map(lambda name, question=question: getattr(question, name, None), field_names)))
[None, 1, 'What is it?', datetime.datetime(2020, 5, 20, 15, 56, 37, 675623, tzinfo=)]
 

There’s a lot going on here, so let’s break it down:
In python 3, map returns a map object instead of a list, so we need to wrap it with list(). Since we’re in pdb, though, list is a function that lists the code around your breakpoint, so we prevent this confusion by wrapping everything in print().

What about question=question? In python 3, lambda expressions have their own scope, so to use variables from the outer scope, we need to “capture” them using this syntax.

As for getattr(question, name, None), getattr is a handy function for retrieving an attribute from an object. It’s like a longhand form of the dot notation (e.g. foo.attr). It’s useful when you need to access attributes dynamically, since dot notation only works with literal attributes. Another handy feature we’re using here is getattr‘s third argument, which is a default value for getattr to return if the attribute doesn’t exist on the object. In our case, getattr would have returned an error without the default argument. _meta.get_fields returns ManyToMany relationships in addition to regular model fields, and ‘choice’ doesn’t actually exist as an attribute of question, because it’s a reverse relationship from the Choice model.

Now that we can get fields and values from a model instance, let’s take things a step further and write a function to list all fields and values of an instance:

def get_field_and_value(instance, field):
        return (field.name, getattr(instance, field.name, None))
   
def list_fields_and_values(instance):
        model = type(instance)
        fields = model._meta.get_fields()
        tuples = []
        for f in fields:
            tuples.append(get_field_and_value(instance, f))
        return tuples
 

Here it is in action:

(Pdb) list_fields_and_values(question)
[('choice', None), ('id', 1), ('question_text', 'What is it?'), ('pub_date', 
datetime.datetime(2020, 5, 20, 15, 56, 37, 675623, tzinfo=))]

This is a handy utility function to keep in your project for debugging and testing. There’s definitely some room for improvement, though. A good next step would be to extend the function to recurse on foreign key fields.

Hopefully this blog post has given you some ideas for how to use _meta to explore Django models. There are a lot of features I haven’t covered, so head over to the official docs if you want to learn more!

Filed Under: Development, Django

© 2021 Cypress Mill Co.